Inheritance, parenting and overriding

Just stumbled upon this quote in an OOP book I am reading,

The child is only allowed to increase functionality and add functionality. A child is never allowed to remove functionality. If you find that the child needs to remove functionality, this indicates that the child should appear before the parent in the inheritance hierarchy!

But my question is, is that not the point?

+1


source to share


6 answers


You can remove functionality with override. But usually you use it to change behavior. For the class to behave as it should.



If the behavior is removed, it is very often a sign of bad class.

+4


source


A child cannot remove functionality - he can change it, but you cannot, for example, make a public method private.



The point of inheritance is that you can treat the child as if it were a parent. If you have a superclass of the Human class and a subclass of Employee, there will be no breathe () method for the Employee class.

+3


source


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

+1


source


Not. In fact you would be increasing the functionality (negatively)

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

You don't have a subclass that removes a method from its parent.

It is possible

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

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

      

But this is not the case:

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
     }
 }

      

+1


source


And what is curious is why overriding (and any virtual participants in general) is something to be done very carefully ... In fact, as a rule of thumb, when overriding, you should try to code both the base class and the derived class, so that the implementation derived class first calls the base implementation and then performs its additional functions ...

but this principle does not apply in OO languages ​​and is often violated ...

An example of why this is bad

Imagine you have models CompanyA Type (class) Phone

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

      

No iagine Company B defines another type of BetterPhone that uses a branded phone A as the base type ...

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

      

Now CompanyA, whose phone class is used by other companies (Company C, D, etc.), decides that establishing a connection is a useful thing in the class and modifies CompanyA.Phone by adding the EsatblishCOnnection () method, possibly with a different implementation. .. Until we had a "new" keyword, this script would break the CompanyB BetterPhone class ... the first time they tried to use the new base class.

0


source


If your child needs to remove the parent's functionality, the parent must be declared as an interface. Because an interface is a mechanism that defines the contracts to be executed by its developer.

eg.


public interface IContract
{
  void DoWork();
}

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

      

Now, if you want to declare a new EnhancedContract class, you can get it from either BaseContract or IContract depending on your requirement. If you want to perform additional operation on base operation A, you can inherit 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 performing operation A in the DoWork EnhancedContract method, inherit it from IContract.

This ensures that the EnhancedWork will execute the DoWork (), but it is not guaranteed to execute the "operation A".


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

      

This is important to understand because it will stop the user from doing the below casting.


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

      

I believe that all of these operations are important in understanding the principle of the Closed the Open , principle of substitution Liskova .

The rule of thumb for inheritance is "Add additional functionality to existing".

0


source







All Articles