0

我遇到了一个问题,我想在父类(A)中有一个方法(M),然后 B 和 C 扩展类 A。在这种情况下,我希望 method(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
4

3 回答 3

1

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

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

Liskov 原则指出:

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

有了你想做的事情,你可能破坏事情。假设您有一个接受父类的方法A,但您将其传递给派生类C。当您的方法尝试调用时会发生什么C.M()

你需要做的是重新思考你的班级设计。如果您不应该调用from ,那么aC 真的是 a的子类型吗?AM()C

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

于 2017-07-13T18:07:47.200 回答
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带着未满足的期望打电话。

于 2017-07-13T18:33:42.417 回答
-1

在这种情况下,我希望 method(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

于 2017-07-13T17:59:29.373 回答