Question

Just came across this quote in a book on OOP that I'm reading,

A child is only allowed to augment functionality and add functionality. A child is never allowed to remove functionality. If you do find that a child need to remove functionality, this is an indication that the child should appear before the parent in the inheritance hierarchy!

But my question is, isn't this what overriding does?

Was it helpful?

Solution

You can remove functionality with overriding. But normally you use it to change the behaviour. To let the class behave as it should be.

If behaviour is removed then it is very often a sign of a bad class design.

OTHER TIPS

The child cannot remove functionality - it can alter it, but you can't, say, make a public method private.

The point of inheritance is that you can handle the child as if it was the parent. If you has a 'Person' superclass a 'Employee' subclass, it would make no sense for the Employee class to have no breathe() method.

When overriding a method, it is possible to call the parent implementation at some point during your override, so using overriding to add functionality to the parent implementation.

No. Actually you would be augmenting functionality ( in a negative way )

Let's say your new functionality is "do nothing" but the method, what the clients of your code see is still the same interface

You cannot have a subclass that remove a method of its parent.

This is possible

class Parent {
    public void method_one(){ 
        print "Hello";
    }
}

class Child extends Parent {
     public void method_one(){
         // do nothing
     }
 }

But this is not:

class Parent {
    public void method_one(){ 
        print "Hello";
    }
}

class Child extends Parent {
     // Attempt remove the method visibility, thus remove funcionality 
     private void method_one(){ 
         // do nothing
     }
 }

And that's kinda why overriding (and in general, any virtual members) is something that should be done very carefully... In fact, generally, when overriding, you should try to code both the base class and the derived class, so that the derived class implementation first calls the base implementation, and then executes it's additional functionality...

but this principle is not enforced in OO languages, and is often violated...

Example of why this is bad

Imagine you have CompanyA designs Type ( class ) Phone

namespace CompanyA {
   class Phone {
       public void Dial() {
        // do work to dial the phone here
       }
   }
}

No iagine Company B defines another type BetterPhone, that uses Company A's Phone as base type...

namespace CompanyB {
   class BetterPhone: CompanyA.Phone {
       public void Dial()  {
           Console.WriteLine("BetterPhoneDial");
           EstablishConenction();
           base.Dial();
       }
   }
}

Now CompanyA, whose Phone class is in use by other Companies (Company C, D, etc.) decides that establishing a connection is a useful thing to have in the class, and modifies CompanyA.Phone, adding an EsatblishCOnnection() method as well, perhaps with a different implementation... Until we had the "new" keyword, this scenario would have broken CompanyB's BetterPhone class... the first time they attempted to use the new base class.

If your child requires to remove functionality of parent, then parent must be declared as Interface. Because Interface is mechanism which defines contracts that must be abide by its implementor.

E.g.


public interface IContract
{
  void DoWork();
}

public class BaseContract: IContract
{
 public virtual void DoWork()
 {
  //perform operation A
 }
}

Now if you want to declare new EnhancedContract class, you can derive it either from BaseContract or IContract depend on requirement. If you want to do additional operation to operation A of base, you can inherit it from BaseContract as shown below.


public class EnhancedContract: BaseContract
{
  public override void DoWork()
  {
   //perform operation B
   base.DoWork();
   //perform operation C
  }
}

But if you are not interested in doing operation A in DoWork method of EnhancedContract, then inherit it from IContract.

This assures that EnhancedWork will perform DoWork(), but it is not guaranteed to do 'operation A' in it.


public class EnhancedWork:IContract
{
  public void DoWork()
  {
   //perform operation D
  }
}

This is important for understading because it will stop user from doing below casting.


EnhancedContract e = new EnhancedContract();
BaseContract b = e;

I believe all these operations are important while understanding Open Closed principle, Liskov substitution principle.

Thumb rule for inheritance is "Put additional functionality into existing one".

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top