1

I was wondering, given the limitations of javascript's prototypal inheritance, would it be possible to emulate class-based inheritance as seen in other OOP languages.

I've created a superclass and subclass as follows:

//Parent
function Animal(i)
{
    //Some constructor implementation
}

//Child
function Pig(i)
{
    //Some additional constructor implementation
}

Pig.prototype = new Animal();

Can I ensure that the child inherits its parent's functions in such a way that I do not need to explicitly call them, or create them in the child object?

Animal.prototype.eat = function()
{
    console.log("eating...");
}

Pig.eat(); //No implementation of eat in the Pig object

Can I ensure that the child inherits all of its parent's object variables in addition to its own ones without explicitly calling the parent's constructor like this:

function Pig(i) 
{
    User.call(this, i);
    //Some pig-like variables
}

Basically, I'd like to create all the implementation in my parent class and only write functions that need to be overridden + any additional functions in the child class. If I want to call Pig.eat(), I'd like it to use the parent function if one doesn't exist in the child object. And upon creating a Pig object, I'd like it to inherit its parent's variables in addition to its own unique ones. Is this possible?

sookie
  • 2,437
  • 3
  • 29
  • 48
  • 4
    First of all, you need to make a `new Pig` *instance* before you can call methods like `eat` on it. And you [should not use `new` to create prototype objects](https://stackoverflow.com/questions/12592913/what-is-the-reason-to-use-the-new-keyword-here) – Bergi Feb 13 '16 at 18:50
  • 3
    No, just like in classical inheritance you always need to explicitly call `super` (here: `Animal.call(this, i);`) every time. Of course, in JS you might be able to get some sugar through metaprogramming here. – Bergi Feb 13 '16 at 18:51
  • 1
    *"Can I ensure that the child inherits its parent's functions in such a way that I do not need to explicitly call them, or create them in the child object?"* It seems you really just need to learn about [how prototypes work](https://github.com/getify/You-Dont-Know-JS/blob/master/this%20&%20object%20prototypes/ch5.md). I encourage you to embrace JavaScript's prototypal inheritance and forgot about class-based inheritance. – Felix Kling Feb 13 '16 at 18:54
  • Related: https://stackoverflow.com/questions/19633762/classical-inheritance-vs-protoypal-inheritance-in-javascript – BSMP Feb 13 '16 at 19:11
  • http://www.crockford.com/javascript/inheritance.html – BSMP Feb 13 '16 at 19:11
  • Everything you describe in your last paragraph works just fine in Javascript's normal prototype inheritance if you are implementing and using it properly. So, it sounds like your main issue is that you just need to learn how to properly use inheritance in Javascript, for which there are thousands of tutorials on the web. – jfriend00 Feb 13 '16 at 19:13
  • While the requirement of inheriting methods via the prototype makes perfect sense, I don't quite get the part of inheriting variables without calling parent constructor. – Wiktor Zychla Feb 13 '16 at 19:20
  • Thank you for your time and answers. My understanding of prototyping was misguided. You can of course do all the standard inheritance with javascript's prototyping. My example works fine. As for inheriting a parent's variables, I meant was it possible to automatically call the parent and child constructors without the use of 'User.call(this, i);' But it seems the child constructor overrides the parent constructor so this statement must be used. Silly interpretation on my end. – sookie Feb 14 '16 at 00:28

2 Answers2

2

I'd like to create all the implementation in my parent class and only write functions that need to be overridden + any additional functions in the child class.

It actually works this way. Probably you just did something a bit wrong, see this example:

//Parent
function Animal()
{
    this.animalInstinct = true;
}

Animal.prototype.eat = function()
{
    alert("eating...");
}

//Child
function Pig()
{
    this.nose = 'pigNose' 
}

Pig.prototype = new Animal();

pig = new Pig();

pig.eat(); //There is implementation of eat in the Pig object

Also note that Pig.prototype = new Animal(); can be problematic in some cases. For example in order to define the Pig class you need to instantiate the Animal object. And this can be not convenient for more complex objects where you need to pass some parameters to the constructor.

Recommended way is to do Pig.prototype = Object.create(Animal.prototype).

Borys Serebrov
  • 15,636
  • 2
  • 38
  • 54
1

Check out the ES6 way, which can be compiled into ES5 easily using something like Babel.

'use strict';
class Animal {
    constructor() {
    }

    eat() {
        console.log('Eating')
        return this;
    }

    play() {
        console.log('Do whatever an animal does...');
        return this;
    }
}

class Pig extends Animal {
    constructor() {
        super()
    }

    play() {
        // This overrides the Animal play method
        console.log('Roll in the mud!');
        return this;
    }

    makeBacon() {
        console.log('BACON!!');
    }
}

If you want see an ES5 version, copy paste the above into Babel's live testing console, or just test that in the latest version of Chrome as it supports it. Then, you can do the following:

var pig = new Pig();
pig.eat().play().eat().makeBacon();
KevBot
  • 17,900
  • 5
  • 50
  • 68