JavaScript OOP Course 4: Prototypical Inheritance: Difference between revisions

From WikiMLT
m (Стадий: 6 [Фаза:Утвърждаване, Статус:Утвърден]; Категория:JavaScript)
 
m (Text replacement - "mlw-continue" to "code-continue")
 
Line 6: Line 6:


==Creating Your Own Prototypical Inheritance==
==Creating Your Own Prototypical Inheritance==
<syntaxhighlight lang="javascript" class="mlw-continue">
<syntaxhighlight lang="javascript" class="code-continue">
function Shape(color) {
function Shape(color) {
     this.color = color;
     this.color = color;
Line 15: Line 15:


const shape = new Shape('red');
const shape = new Shape('red');
</syntaxhighlight><syntaxhighlight lang="javascript" class="mlw-continue">
</syntaxhighlight><syntaxhighlight lang="javascript" class="code-continue">
Object.getPrototypeOf(shape);
Object.getPrototypeOf(shape);
</syntaxhighlight><syntaxhighlight lang="shell-session" class="mlw-continue">
</syntaxhighlight><syntaxhighlight lang="shell-session" class="code-continue">
{duplicate: ƒ, constructor: ƒ}
{duplicate: ƒ, constructor: ƒ}
     duplicate: ƒ ()
     duplicate: ƒ ()
     constructor: ƒ Shape(color)
     constructor: ƒ Shape(color)
     [[Prototype]]: Object
     [[Prototype]]: Object
</syntaxhighlight>Now we want to inherit the <code>duplicate()</code> method by another type of objects, like Circle and Square.<syntaxhighlight lang="javascript" class="mlw-continue">
</syntaxhighlight>Now we want to inherit the <code>duplicate()</code> method by another type of objects, like Circle and Square.<syntaxhighlight lang="javascript" class="code-continue">
function Circle(radius) {
function Circle(radius) {
     this.radius = radius;
     this.radius = radius;
Line 31: Line 31:


const circle1 = new Circle(1);
const circle1 = new Circle(1);
</syntaxhighlight>Note the Constructor here is <code>''ƒ Circle(radius)''</code>.<syntaxhighlight lang="javascript" class="mlw-continue">
</syntaxhighlight>Note the Constructor here is <code>''ƒ Circle(radius)''</code>.<syntaxhighlight lang="javascript" class="code-continue">
Object.getPrototypeOf(circle1);
Object.getPrototypeOf(circle1);
</syntaxhighlight><syntaxhighlight lang="shell-session" class="mlw-continue">
</syntaxhighlight><syntaxhighlight lang="shell-session" class="code-continue">
{draw: ƒ, constructor: ƒ}
{draw: ƒ, constructor: ƒ}
     draw: ƒ ()
     draw: ƒ ()
     constructor: ƒ Circle(radius)
     constructor: ƒ Circle(radius)
     [[Prototype]]: Object
     [[Prototype]]: Object
</syntaxhighlight>Change the Prototype of the Constructor and create a new Object at this Base.<syntaxhighlight lang="javascript" class="mlw-continue">
</syntaxhighlight>Change the Prototype of the Constructor and create a new Object at this Base.<syntaxhighlight lang="javascript" class="code-continue">
Circle.prototype = Object.create(Shape.prototype);
Circle.prototype = Object.create(Shape.prototype);
const circle2 = new Circle(2);
const circle2 = new Circle(2);
</syntaxhighlight>Note now the Constructor is <code>''ƒ Shape(color)''</code>.<syntaxhighlight lang="javascript" class="mlw-continue">
</syntaxhighlight>Note now the Constructor is <code>''ƒ Shape(color)''</code>.<syntaxhighlight lang="javascript" class="code-continue">
Object.getPrototypeOf(circle2);
Object.getPrototypeOf(circle2);
</syntaxhighlight><syntaxhighlight lang="shell-session" class="mlw-continue">
</syntaxhighlight><syntaxhighlight lang="shell-session" class="code-continue">
Shape {}
Shape {}
     [[Prototype]]: Object
     [[Prototype]]: Object
Line 49: Line 49:
         constructor: ƒ Shape(color)
         constructor: ƒ Shape(color)
         [[Prototype]]: Object
         [[Prototype]]: Object
</syntaxhighlight><syntaxhighlight lang="javascript" class="mlw-continue">
</syntaxhighlight><syntaxhighlight lang="javascript" class="code-continue">
circle2.duplicate();
circle2.duplicate();
</syntaxhighlight><syntaxhighlight lang="shell-session" class="mlw-continue">
</syntaxhighlight><syntaxhighlight lang="shell-session" class="code-continue">
duplicate
duplicate
</syntaxhighlight>
</syntaxhighlight>
Line 57: Line 57:
== Resetting the Constructor ==
== Resetting the Constructor ==


As best practice when we reset the Prototype make sure you reset the constructor as well. Let's continue by the last example, where we saw when the Prototype was changed to <code>Shape</code> also the Constructor was changed to <code>Shape</code>, here is how to set it back to <code>Circle</code>''.''<syntaxhighlight lang="javascript" class="mlw-continue">
As best practice when we reset the Prototype make sure you reset the constructor as well. Let's continue by the last example, where we saw when the Prototype was changed to <code>Shape</code> also the Constructor was changed to <code>Shape</code>, here is how to set it back to <code>Circle</code>''.''<syntaxhighlight lang="javascript" class="code-continue">
Circle.prototype = Object.create(Shape.prototype);
Circle.prototype = Object.create(Shape.prototype);
Circle.prototype.constructor = Circle;
Circle.prototype.constructor = Circle;
const circle3 = new Circle(3);
const circle3 = new Circle(3);
</syntaxhighlight>Note in the example below the Constructor is changed back to <code>Circle</code>.<syntaxhighlight lang="javascript" class="mlw-continue">
</syntaxhighlight>Note in the example below the Constructor is changed back to <code>Circle</code>.<syntaxhighlight lang="javascript" class="code-continue">
Object.getPrototypeOf(circle3);
Object.getPrototypeOf(circle3);
</syntaxhighlight><syntaxhighlight lang="shell-session" class="mlw-continue">
</syntaxhighlight><syntaxhighlight lang="shell-session" class="code-continue">
Shape {constructor: ƒ}
Shape {constructor: ƒ}
     constructor: ƒ Circle(radius)
     constructor: ƒ Circle(radius)
Line 73: Line 73:


== Calling the Super Constructor ==
== Calling the Super Constructor ==
<syntaxhighlight lang="javascript" class="mlw-continue">
<syntaxhighlight lang="javascript" class="code-continue">
function Shape(color) {
function Shape(color) {
     this.color = color;
     this.color = color;
Line 80: Line 80:
     console.log('duplicate');
     console.log('duplicate');
};
};
</syntaxhighlight><syntaxhighlight lang="javascript" class="mlw-continue">
</syntaxhighlight><syntaxhighlight lang="javascript" class="code-continue">
function Circle(radius, color) {
function Circle(radius, color) {
     Shape.call(this, color);
     Shape.call(this, color);
Line 88: Line 88:
     console.log('draw');
     console.log('draw');
};
};
</syntaxhighlight><syntaxhighlight lang="javascript" class="mlw-continue">
</syntaxhighlight><syntaxhighlight lang="javascript" class="code-continue">
Circle.prototype = Object.create(Shape.prototype);
Circle.prototype = Object.create(Shape.prototype);
Circle.prototype.constructor = Circle;
Circle.prototype.constructor = Circle;
</syntaxhighlight><syntaxhighlight lang="javascript" class="mlw-continue">
</syntaxhighlight><syntaxhighlight lang="javascript" class="code-continue">
const shape = new Shape('red');
const shape = new Shape('red');
const circle = new Circle(10, 'blue');
const circle = new Circle(10, 'blue');
</syntaxhighlight><syntaxhighlight lang="javascript" class="mlw-continue">
</syntaxhighlight><syntaxhighlight lang="javascript" class="code-continue">
circle;
circle;
</syntaxhighlight><syntaxhighlight lang="shell-session" class="mlw-continue">
</syntaxhighlight><syntaxhighlight lang="shell-session" class="code-continue">
Circle {color: 'blue', radius: 10}
Circle {color: 'blue', radius: 10}
     color: "blue"
     color: "blue"
Line 109: Line 109:


== Intermediate Function Inheritance ==
== Intermediate Function Inheritance ==
<syntaxhighlight lang="javascript" class="mlw-continue">
<syntaxhighlight lang="javascript" class="code-continue">
function Shape(color) {
function Shape(color) {
     this.color = color;
     this.color = color;
Line 116: Line 116:
     console.log('duplicate');
     console.log('duplicate');
};
};
</syntaxhighlight><syntaxhighlight lang="javascript" class="mlw-continue">
</syntaxhighlight><syntaxhighlight lang="javascript" class="code-continue">
function Square(size, color) {
function Square(size, color) {
     Shape.call(this, color);
     Shape.call(this, color);
     this.size = size;
     this.size = size;
}
}
</syntaxhighlight><syntaxhighlight lang="javascript" class="mlw-continue">
</syntaxhighlight><syntaxhighlight lang="javascript" class="code-continue">
Square.prototype = Object.create(Shape.prototype);
Square.prototype = Object.create(Shape.prototype);
Square.prototype.constructor = Square;
Square.prototype.constructor = Square;
</syntaxhighlight><syntaxhighlight lang="javascript" class="mlw-continue">
</syntaxhighlight><syntaxhighlight lang="javascript" class="code-continue">
const square = new Square(10, 'green');
const square = new Square(10, 'green');
</syntaxhighlight><syntaxhighlight lang="javascript" class="mlw-continue">
</syntaxhighlight><syntaxhighlight lang="javascript" class="code-continue">
square;
square;
</syntaxhighlight><syntaxhighlight lang="shell-session" class="mlw-continue">
</syntaxhighlight><syntaxhighlight lang="shell-session" class="code-continue">
Square {color: 'green', size: 10}
Square {color: 'green', size: 10}
     color: "green"
     color: "green"
Line 138: Line 138:
             constructor: ƒ Shape(color)
             constructor: ƒ Shape(color)
             [[Prototype]]: Object
             [[Prototype]]: Object
</syntaxhighlight>Now let's rewrite the above code and extract the two lines that changes the Prototype and the Constructor in a Function that we can reuse multiple times.<syntaxhighlight lang="javascript" class="mlw-continue">
</syntaxhighlight>Now let's rewrite the above code and extract the two lines that changes the Prototype and the Constructor in a Function that we can reuse multiple times.<syntaxhighlight lang="javascript" class="code-continue">
function extend(Child, Parent) {
function extend(Child, Parent) {
     Child.prototype = Object.create(Parent.prototype);
     Child.prototype = Object.create(Parent.prototype);
     Child.prototype.constructor = Child;
     Child.prototype.constructor = Child;
}
}
</syntaxhighlight>This <code>extend()</code> function is what we call Intermediate function inheritance. Here is how to use it.<syntaxhighlight lang="javascript" class="mlw-continue">
</syntaxhighlight>This <code>extend()</code> function is what we call Intermediate function inheritance. Here is how to use it.<syntaxhighlight lang="javascript" class="code-continue">
function Shape(color) {
function Shape(color) {
     this.color = color;
     this.color = color;
}
}
Shape.prototype.duplicate = function() { console.log('duplicate'); };
Shape.prototype.duplicate = function() { console.log('duplicate'); };
</syntaxhighlight><syntaxhighlight lang="javascript" class="mlw-continue">
</syntaxhighlight><syntaxhighlight lang="javascript" class="code-continue">
function Circle(radius) {
function Circle(radius) {
     this.radius = radius;
     this.radius = radius;
}
}
extend(Circle, Shape);
extend(Circle, Shape);
</syntaxhighlight><syntaxhighlight lang="javascript" class="mlw-continue">
</syntaxhighlight><syntaxhighlight lang="javascript" class="code-continue">
function Square(size) {
function Square(size) {
     this.size = size;
     this.size = size;
}
}
extend(Square, Shape);
extend(Square, Shape);
</syntaxhighlight><syntaxhighlight lang="javascript" class="mlw-continue">
</syntaxhighlight><syntaxhighlight lang="javascript" class="code-continue">
const circle = new Circle(10);
const circle = new Circle(10);
const square = new Square(10);
const square = new Square(10);
</syntaxhighlight><syntaxhighlight lang="javascript" class="mlw-continue">
</syntaxhighlight><syntaxhighlight lang="javascript" class="code-continue">
circle;
circle;
</syntaxhighlight><syntaxhighlight lang="shell-session" class="mlw-continue">
</syntaxhighlight><syntaxhighlight lang="shell-session" class="code-continue">
Circle {radius: 10}
Circle {radius: 10}
     radius: 10
     radius: 10
Line 172: Line 172:
             constructor: ƒ Shape(color)
             constructor: ƒ Shape(color)
             [[Prototype]]: Object
             [[Prototype]]: Object
</syntaxhighlight><syntaxhighlight lang="javascript" class="mlw-continue">
</syntaxhighlight><syntaxhighlight lang="javascript" class="code-continue">
square;
square;
</syntaxhighlight><syntaxhighlight lang="shell-session" class="mlw-continue">
</syntaxhighlight><syntaxhighlight lang="shell-session" class="code-continue">
Square {size: 10}
Square {size: 10}
size: 10
size: 10
Line 186: Line 186:


== Method Overriding ==
== Method Overriding ==
<syntaxhighlight lang="javascript" class="mlw-continue">
<syntaxhighlight lang="javascript" class="code-continue">
function extend(Child, Parent) {
function extend(Child, Parent) {
     Child.prototype = Object.create(Parent.prototype);
     Child.prototype = Object.create(Parent.prototype);
Line 202: Line 202:


const circle = new Circle();
const circle = new Circle();
</syntaxhighlight><syntaxhighlight lang="javascript" class="mlw-continue">
</syntaxhighlight><syntaxhighlight lang="javascript" class="code-continue">
circle;
circle;
</syntaxhighlight><syntaxhighlight lang="shell-session" class="mlw-continue">
</syntaxhighlight><syntaxhighlight lang="shell-session" class="code-continue">
Circle {}
Circle {}
     [[Prototype]]: Shape
     [[Prototype]]: Shape
Line 212: Line 212:
         constructor: ƒ Shape()
         constructor: ƒ Shape()
         [[Prototype]]: Object
         [[Prototype]]: Object
</syntaxhighlight><syntaxhighlight lang="javascript" class="mlw-continue">
</syntaxhighlight><syntaxhighlight lang="javascript" class="code-continue">
circle.duplicate();
circle.duplicate();
</syntaxhighlight><syntaxhighlight lang="shell-session" class="mlw-continue">
</syntaxhighlight><syntaxhighlight lang="shell-session" class="code-continue">
duplicate
duplicate
</syntaxhighlight>Now let's imagine the duplicate() method should behave differently at Circle objects. In order to override this method (or reimplementing a method on a child object) we need to put our declaration '''after the resetting the prototype''' by the <code>extend()</code> function.<syntaxhighlight lang="javascript" class="mlw-continue">
</syntaxhighlight>Now let's imagine the duplicate() method should behave differently at Circle objects. In order to override this method (or reimplementing a method on a child object) we need to put our declaration '''after the resetting the prototype''' by the <code>extend()</code> function.<syntaxhighlight lang="javascript" class="code-continue">
Circle.prototype.duplicate = function() {  
Circle.prototype.duplicate = function() {  
     console.log('duplicate circle');  
     console.log('duplicate circle');  
};
};
</syntaxhighlight><syntaxhighlight lang="javascript" class="mlw-continue">
</syntaxhighlight><syntaxhighlight lang="javascript" class="code-continue">
circle.duplicate();
circle.duplicate();
</syntaxhighlight><syntaxhighlight lang="shell-session" class="mlw-continue">
</syntaxhighlight><syntaxhighlight lang="shell-session" class="code-continue">
duplicate circle
duplicate circle
</syntaxhighlight>
</syntaxhighlight>


== Polymorphism ==
== Polymorphism ==
Polymorphism - many form. In the following example the polymorphism manifests in the <code>duplicate()</code> method which is specific for each type of shape...<syntaxhighlight lang="javascript" class="mlw-continue">
Polymorphism - many form. In the following example the polymorphism manifests in the <code>duplicate()</code> method which is specific for each type of shape...<syntaxhighlight lang="javascript" class="code-continue">
function extend(Child, Parent) {
function extend(Child, Parent) {
     Child.prototype = Object.create(Parent.prototype);
     Child.prototype = Object.create(Parent.prototype);
Line 249: Line 249:
     console.log('duplicate square');  
     console.log('duplicate square');  
};
};
</syntaxhighlight>Let's define an array of shape objects.<syntaxhighlight lang="javascript" class="mlw-continue">
</syntaxhighlight>Let's define an array of shape objects.<syntaxhighlight lang="javascript" class="code-continue">
const shapes = [
const shapes = [
     new Circle(),
     new Circle(),
     new Square()
     new Square()
];
];
</syntaxhighlight>Now we can iterate over this array by using <code>for.. of..</code> loop in the following way.<syntaxhighlight lang="javascript" class="mlw-continue">
</syntaxhighlight>Now we can iterate over this array by using <code>for.. of..</code> loop in the following way.<syntaxhighlight lang="javascript" class="code-continue">
for (let shape of shapes)
for (let shape of shapes)
     shape.duplicate();
     shape.duplicate();
</syntaxhighlight><syntaxhighlight lang="shell-session" class="mlw-continue">
</syntaxhighlight><syntaxhighlight lang="shell-session" class="code-continue">
duplicate circle
duplicate circle
duplicate square
duplicate square

Latest revision as of 08:29, 26 September 2022

Ref­er­ences

Cre­at­ing Your Own Pro­to­typ­i­cal In­her­i­tance

function Shape(color) {
    this.color = color;
}
Shape.prototype.duplicate = function() {
    console.log('duplicate');
};

const shape = new Shape('red');
Object.getPrototypeOf(shape);
{duplicate: ƒ, constructor: ƒ}
    duplicate: ƒ ()
    constructor: ƒ Shape(color)
    [[Prototype]]: Object

Now we want to in­her­it the du­pli­cate() method by an­oth­er type of ob­jects, like Cir­cle and Square.

function Circle(radius) {
    this.radius = radius;
}
Circle.prototype.draw = function() {
    console.log('draw');
};

const circle1 = new Circle(1);

Note the Con­struc­tor here is ƒ Circle(radius).

Object.getPrototypeOf(circle1);
{draw: ƒ, constructor: ƒ}
    draw: ƒ ()
    constructor: ƒ Circle(radius)
    [[Prototype]]: Object

Change the Pro­to­type of the Con­struc­tor and cre­ate a new Ob­ject at this Base.

Circle.prototype = Object.create(Shape.prototype);
const circle2 = new Circle(2);

Note now the Con­struc­tor is ƒ Shape(color).

Object.getPrototypeOf(circle2);
Shape {}
    [[Prototype]]: Object
        duplicate: ƒ ()
        constructor: ƒ Shape(color)
        [[Prototype]]: Object
circle2.duplicate();
duplicate

Re­set­ting the Con­struc­tor

As best prac­tice when we re­set the Pro­to­type make sure you re­set the con­struc­tor as well. Let's con­tin­ue by the last ex­am­ple, where we saw when the Pro­to­type was changed to Shape al­so the Con­struc­tor was changed to Shape, here is how to set it back to Cir­cle.

Circle.prototype = Object.create(Shape.prototype);
Circle.prototype.constructor = Circle;
const circle3 = new Circle(3);

Note in the ex­am­ple be­low the Con­struc­tor is changed back to Cir­cle.

Object.getPrototypeOf(circle3);
Shape {constructor: ƒ}
    constructor: ƒ Circle(radius)
    [[Prototype]]: Object
        duplicate: ƒ ()
        constructor: ƒ Shape(color)
        [[Prototype]]: Object

Call­ing the Su­per Con­struc­tor

function Shape(color) {
    this.color = color;
}
Shape.prototype.duplicate = function() {
    console.log('duplicate');
};
function Circle(radius, color) {
    Shape.call(this, color);
    this.radius = radius;
}
Circle.prototype.draw = function() {
    console.log('draw');
};
Circle.prototype = Object.create(Shape.prototype);
Circle.prototype.constructor = Circle;
const shape = new Shape('red');
const circle = new Circle(10, 'blue');
circle;
Circle {color: 'blue', radius: 10}
    color: "blue"
    radius: 10
    [[Prototype]]: Shape
        constructor: ƒ Circle(radius, color)
        [[Prototype]]: Object
            duplicate: ƒ ()
            constructor: ƒ Shape(color)
            [[Prototype]]: Object

In­ter­me­di­ate Func­tion In­her­i­tance

function Shape(color) {
    this.color = color;
}
Shape.prototype.duplicate = function() {
    console.log('duplicate');
};
function Square(size, color) {
    Shape.call(this, color);
    this.size = size;
}
Square.prototype = Object.create(Shape.prototype);
Square.prototype.constructor = Square;
const square = new Square(10, 'green');
square;
Square {color: 'green', size: 10}
    color: "green"
    size: 10
    [[Prototype]]: Shape
        constructor: ƒ Square(size, color)
        [[Prototype]]: Object
            duplicate: ƒ ()
            constructor: ƒ Shape(color)
            [[Prototype]]: Object

Now let's rewrite the above code and ex­tract the two lines that changes the Pro­to­type and the Con­struc­tor in a Func­tion that we can reuse mul­ti­ple times.

function extend(Child, Parent) {
    Child.prototype = Object.create(Parent.prototype);
    Child.prototype.constructor = Child;
}

This ex­tend() func­tion is what we call In­ter­me­di­ate func­tion in­her­i­tance. Here is how to use it.

function Shape(color) {
    this.color = color;
}
Shape.prototype.duplicate = function() { console.log('duplicate'); };
function Circle(radius) {
    this.radius = radius;
}
extend(Circle, Shape);
function Square(size) {
    this.size = size;
}
extend(Square, Shape);
const circle = new Circle(10);
const square = new Square(10);
circle;
Circle {radius: 10}
    radius: 10
    [[Prototype]]: Shape
        constructor: ƒ Circle(radius)
        [[Prototype]]: Object
            duplicate: ƒ ()
            constructor: ƒ Shape(color)
            [[Prototype]]: Object
square;
Square {size: 10}
size: 10
    [[Prototype]]: Shape
        constructor: ƒ Square(size)
        [[Prototype]]: Object
            duplicate: ƒ ()
            constructor: ƒ Shape(color)
            [[Prototype]]: Object

Method Over­rid­ing

function extend(Child, Parent) {
    Child.prototype = Object.create(Parent.prototype);
    Child.prototype.constructor = Child;
}

function Shape() { }
Shape.prototype.duplicate = function() { 
    console.log('duplicate'); 
};

function Circle() { }

extend(Circle, Shape);

const circle = new Circle();
circle;
Circle {}
    [[Prototype]]: Shape
    constructor: ƒ Circle()
    [[Prototype]]: Object
        duplicate: ƒ ()
        constructor: ƒ Shape()
        [[Prototype]]: Object
circle.duplicate();
duplicate

Now let's imag­ine the du­pli­cate() method should be­have dif­fer­ent­ly at Cir­cle ob­jects. In or­der to over­ride this method (or reim­ple­ment­ing a method on a child ob­ject) we need to put our de­c­la­ra­tion af­ter the re­set­ting the pro­to­type by the ex­tend() func­tion.

Circle.prototype.duplicate = function() { 
    console.log('duplicate circle'); 
};
circle.duplicate();
duplicate circle

Poly­mor­phism

Poly­mor­phism – many form. In the fol­low­ing ex­am­ple the poly­mor­phism man­i­fests in the du­pli­cate() method which is spe­cif­ic for each type of shape…

function extend(Child, Parent) {
    Child.prototype = Object.create(Parent.prototype);
    Child.prototype.constructor = Child;
}

function Shape() { }
Shape.prototype.duplicate = function() { 
    console.log('duplicate'); 
};

function Circle() { }
extend(Circle, Shape);
Circle.prototype.duplicate = function() { 
    console.log('duplicate circle'); 
};

function Square() { }
extend(Square, Shape);
Square.prototype.duplicate = function() { 
    console.log('duplicate square'); 
};

Let's de­fine an ar­ray of shape ob­jects.

const shapes = [
    new Circle(),
    new Square()
];

Now we can it­er­ate over this ar­ray by us­ing for.. of.. loop in the fol­low­ing way.

for (let shape of shapes)
    shape.duplicate();
duplicate circle
duplicate square

When to Use In­her­i­tance

Figure 1. JavaScript In­her­i­tance vs Com­po­si­tion.
  • In­her­i­tance is great tool to solv­ing the prob­lem of code reuse. You have to be re­al­ly care­ful about us­ing it be­cause it can make your source code com­plex and frag­ile, so don't use in­her­i­tance just for the sake of us­ing it, es­pe­cial­ly in small projects. Keep it sim­ple and stu­pid.
  • Start with sim­ple ob­jects and then if you see num­ber of these ob­jects share sim­i­lar fea­tures then per­haps you can en­cap­su­late these fea­tures in­side of an gener­ic ob­ject and use in­her­i­tance.
  • But re­mem­ber in­her­i­tance is not the on­ly so­lu­tion that en­abled code reuse. There is an­oth­er tech­nique called Com­po­si­tion (that can be used for the same pur­pose). Fa­vor Com­po­si­tion over In­her­i­tance.
  • Avoid cre­at­ing in­her­i­tance hi­er­ar­chies, be­cause they are very frag­ile. If you want to use in­her­i­tance keep it to one lev­el – do not go than more one lev­el of in­her­i­tance.