Search code examples
javascriptcompositionprototypal-inheritance

Real inheritance in JavaScript


I tried to implement prototypical inheritance between two AngularJS services and one generic service, but this seems not enough to serve my needs.

I made ChildService, SecondChildService and ParentService.

  • ChildService extends ParentService with prototypical inheritance
  • SecondChildService extends ParentService with prototypical inheritance

ParentService has a method let's call it logIt() that logs property it

  • ChildService implements its own version of it
  • SecondChildService implements its own version of it

Now I consider ParentService as the "base class", and I have a method within ParentService that calls logIt(), that is initialize(). This is only implemented in ParentService

I need to run ChildService.initialize() and see that the it of ChildService gets logged. The same thing with SecondChildService.

Instead the ParentService logs its own version of it. The reason I believe is that prototypical inheritance is a composition implementation rather than real inheritance

Can you please propose a workaround?


Edit:

This is my parent service

angular.module('common').service('parentService', ParentService);
ParentService.$inject = [];

/* @ngInject */
function ParentService() {
  'use strict';
  var vm = this;
  vm.it = "parent";

  vm.initialize = function () {
    vm.logIt();
  };

  vm.logIt = function () {
    console.log(this.it);
  };
}

This is my child service

angular.module('common').service('childService', ChildService);
ChildService.$inject = ['parentService'];

/* @ngInject */
function ChildService(parentService) {
  'use strict';
  var vm = this;
  angular.extend(this, parentService);
  vm.it = "child";
}

And this is what I get in the log when I run childService.initialize()

parent

I am expecting to get child instead


Solution

  • The problem is in ParentService. I am using vm.logIt, while I should be using this.logIt in order to get the it from the child service scope. Contrary to standard inheritance, it seems that in prototypical inheritance the logIt() function exists twice, once in the ParentService and once in the ChildService (inherited from parent). With this.logIt() you can call it from the child and it actually gets the it from the child, while with vm.logIt() you call it from the parent where it gets the it from. It is a matter of scope.

    This is the correct implementation of ParentService:

    angular.module('common').service('parentService', ParentService);
    ParentService.$inject = [];
    
    /* @ngInject */
    function ParentService() {
      'use strict';
      var vm = this;
      vm.it = "parent";
    
      vm.initialize = function () {
        this.logIt(); // <-- this changed
      };
    
      vm.logIt = function () {
        console.log(this.it);
      };
    }