function ArraySyncManager(firebaseArray) {
        function destroy(err) {
          if( !sync.isDestroyed ) {
            sync.isDestroyed = true;
            var ref = firebaseArray.$ref();
            ref.off('child_added', created);
            ref.off('child_moved', moved);
            ref.off('child_changed', updated);
            ref.off('child_removed', removed);
            firebaseArray = null;
            initComplete(err||'destroyed');
          }
        }

        function init($list) {
          var ref = firebaseArray.$ref();

          // listen for changes at the Firebase instance
          ref.on('child_added', created, error);
          ref.on('child_moved', moved, error);
          ref.on('child_changed', updated, error);
          ref.on('child_removed', removed, error);

          // determine when initial load is completed
          ref.once('value', function(snap) {
            if (angular.isArray(snap.val())) {
              $log.warn('Storing data using array indices in Firebase can result in unexpected behavior. See https://firebase.google.com/docs/database/web/structure-data for more information.');
            }

            initComplete(null, $list);
          }, initComplete);
        }

        // call initComplete(), do not call this directly
        function _initComplete(err, result) {
          if( !isResolved ) {
            isResolved = true;
            if( err ) { def.reject(err); }
            else { def.resolve(result); }
          }
        }

        var def = $q.defer();
        var created = function(snap, prevChild) {
          if (!firebaseArray) {
            return;
          }
          waitForResolution(firebaseArray.$$added(snap, prevChild), function(rec) {
            firebaseArray.$$process('child_added', rec, prevChild);
          });
        };
        var updated = function(snap) {
          if (!firebaseArray) {
            return;
          }
          var rec = firebaseArray.$getRecord(snap.key);
          if( rec ) {
            waitForResolution(firebaseArray.$$updated(snap), function() {
              firebaseArray.$$process('child_changed', rec);
            });
          }
        };
        var moved   = function(snap, prevChild) {
          if (!firebaseArray) {
            return;
          }
          var rec = firebaseArray.$getRecord(snap.key);
          if( rec ) {
            waitForResolution(firebaseArray.$$moved(snap, prevChild), function() {
              firebaseArray.$$process('child_moved', rec, prevChild);
            });
          }
        };
        var removed = function(snap) {
          if (!firebaseArray) {
            return;
          }
          var rec = firebaseArray.$getRecord(snap.key);
          if( rec ) {
            waitForResolution(firebaseArray.$$removed(snap), function() {
               firebaseArray.$$process('child_removed', rec);
            });
          }
        };

        function waitForResolution(maybePromise, callback) {
          var promise = $q.when(maybePromise);
          promise.then(function(result){
            if (result) {
              callback(result);
            }
          });
          if (!isResolved) {
            resolutionPromises.push(promise);
          }
        }

        var resolutionPromises = [];
        var isResolved = false;
        var error   = $firebaseUtils.batch(function(err) {
          _initComplete(err);
          if( firebaseArray ) {
            firebaseArray.$$error(err);
          }
        });
        var initComplete = $firebaseUtils.batch(_initComplete);

        var sync = {
          destroy: destroy,
          isDestroyed: false,
          init: init,
          ready: function() { return def.promise.then(function(result){
            return $q.all(resolutionPromises).then(function(){
              return result;
            });
          }); }
        };

        return sync;
      }
This method allows FirebaseArray to be inherited by child classes. Methods passed into this
function will be added onto the array's prototype. They can override existing methods as
well.

In addition to passing additional methods, it is also possible to pass in a class function.
The prototype on that class function will be preserved, and it will inherit from
FirebaseArray. It's also possible to do both, passing a class to inherit and additional
methods to add onto the prototype.

 <pre><code>
var ExtendedArray = $firebaseArray.$extend({
   // add a method onto the prototype that sums all items in the array
   getSum: function() {
      var ct = 0;
      angular.forEach(this.$list, function(rec) { ct += rec.x; });
     return ct;
   }
});

// use our new factory in place of $firebaseArray
var list = new ExtendedArray(ref);
</code></pre>

@param {Function} [ChildClass] a child class which should inherit FirebaseArray
@param {Object} [methods] a list of functions to add onto the prototype
@returns {Function} a child class suitable for use with $firebase (this will be ChildClass if provided)
@static