继承,父子和覆盖

时间:2008-11-28 21:09:31

标签: inheritance override parent-child

刚刚在我正在阅读的关于OOP的书中看到了这句话,

  

只允许孩子补充   功能和添加功能。   永远不允许儿童移除   功能。如果你确实找到了   孩子需要删除功能,   这表明孩子   应该出现在父母之前   继承层次结构!

但我的问题是,这不是最重要的吗?

6 个答案:

答案 0 :(得分:4)

您可以通过覆盖删除功能。但通常你用它来改变行为。让班级表现得应该如此。

如果删除了行为,那么这往往是一个糟糕的课程设计的标志。

答案 1 :(得分:3)

孩子无法删除功能 - 它可以改变它,但是你不能将公共方法设为私有。

继承点是你可以像对待父母那样处理孩子。如果你有一个'Person'超类是一个'Employee'子类,那么Employee类没有没有pache()方法就没有意义。

答案 2 :(得分:1)

覆盖方法时,可以在覆盖期间的某个时刻调用父实现,因此使用覆盖来向父实现添加功能。

答案 3 :(得分:1)

没有。实际上你会增加功能(以负面的方式)

假设您的新功能是“什么都不做”,但代码的客户端看到的方法仍然是接口

您不能拥有删除其父级方法的子类。

这是可能的

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

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

但这不是:

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

答案 4 :(得分:0)

这就是为什么覆盖(以及一般来说,任何虚拟成员)都应该非常谨慎地完成的事情...... 实际上,通常,在重写时,您应该尝试对基类和派生类进行编码,以便派生类实现首先调用基本实现,然后执行它的附加功能......

但是这个原则并没有在OO语言中强制实施,而且经常被违反......

为什么这是不好的例子

想象一下,你有CompanyA设计类型(类)电话

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

没有iagine公司B定义另一种类型BetterPhone,它使用公司A的电话作为基本类型......

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

现在,其他公司(公司C,D等)正在使用其电话类的CompanyA决定在类中建立连接是有用的,并修改CompanyA.Phone,添加EsatblishCOnnection()方法也许,可能有不同的实现......在我们使用“new”关键字之前,这个场景会破坏CompanyB的BetterPhone类......这是他们第一次尝试使用新的基类。

答案 5 :(得分:0)

如果您的孩子需要删除父级的功能,则必须将父级声明为Interface。 因为Interface是定义必须遵守其实现者的契约的机制。

E.g。


public interface IContract
{
  void DoWork();
}

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

现在,如果要声明新的EnhancedContract类,可以从BaseContract或IContract派生它,具体取决于要求。 如果要对base的操作A执行其他操作,可以从BaseContract继承它,如下所示。


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

但如果您对在EnhancedContract的DoWork方法中执行操作A不感兴趣,那么从IContract继承它。

这确保了EnhancedWork将执行DoWork(),但不保证在其中执行'操作A'。


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

这对于提示非常重要,因为它会阻止用户进行以下投射。


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

我相信所有这些操作在理解Open Closed principleLiskov substitution principle时非常重要。

继承的Thumb规则是“将其他功能添加到现有功能中”。