我遇到了一个问题,我希望在父类(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
答案 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
将无效执行。