我们可以在父类中定义一个方法,该方法可以在子节点中调用,但不能在另一个子节点中调用

时间:2017-07-13 17:52:33

标签: c# inheritance parent-child derived-class access-levels

我遇到了一个问题,我希望在父类(A)中有一个方法(M),然后B和C扩展A类。在这种情况下,我希望方法(M)可以由B访问,但不能访问C.任何解决方案?

public class A
{
    ????? string M()
    {
        return "Hi there";
    }
}
public class B:A
{
}
public class C:A
{
}
B newClassB = new B();
C newClassC = new C();
Console.WriteLine(newClassB.M()); //the correct one
Console.WriteLine(newClassC.M()); //the incorrect one

3 个答案:

答案 0 :(得分:1)

其他一些答案似乎鼓励您违反Liskov Substitution Principle,这是非常糟糕的做法,只会导致糟糕的代码。

这里有一个设计问题。如果您希望C继承A,那么它应该与A完全相同,但具有添加或修改的功能。

Liskov原则声明:

  

“程序中的对象应该可以替换为其子类型的实例,而不会改变该程序的正确性。”

根据您的目标,您可以潜在破坏事物。假设您有一个方法接受您的父类A,但您传递了派生类C。当您的方法尝试调用C.M()时会发生什么?

您需要做的是重新考虑您的课堂设计。如果您不应该从C拨打A,那么M() 是否真的C的子类型?

您的问题代码非常模糊,因此我无法为您的课程结构提出替代解决方案,但如果您可以使代码不那么模糊,我会进行编辑。

答案 1 :(得分:0)

好的,一个有用的答案(我之前的答案不是)。

不,你不能也不应该这样做,因为Liskov替代原则已在其他答案和评论中指出。

但是,有些情况下可以证明它是合理的,事实上,NET中的某些类确实实现了以下模式:

public class A
{
    public virtual bool CanCallM => true;
    public void M() {
        if (!CanCallM) throw new NotSupportedException();
        //do whatever }
}

public class B: A { }

public class C: A
{
    public override bool CanCallM => false;
}

漂亮?并不多,但如果可以调用M,那么您确实可以让消费者知道事先,并确保在运行时c.M失败。

我个人更喜欢这种模式,因为后者可能是代码中的错误;有人正在调用M,期望得不到满足。

答案 2 :(得分:-1)

  

在这种情况下,我希望方法(M)可以被B访问但不能访问C.任何解决方案?

你不能这样做,正如我在评论中所说的那样,但你可以这样做:

class A 
{

  public virtual bool Before() { return false; }

  public void BaseMethod () 
  {         
      if(Before())
         Console.WriteLine("Called method AMethod");
  }
}

class B : A 
{    
    public override bool Before() {return true; }
}

class C : A 
{    
}

void Main()
{
    var c = new C(); 
    var b = new B(); 

    c.BaseMethod(); 
    b.BaseMethod();
}

在这种情况下,BaseMethod()实例的C将无效执行。