假设我有公共方法A和B的BaseClass,我通过继承创建DerivedClass.
例如
public DerivedClass : BaseClass {}
Run Code Online (Sandbox Code Playgroud)
现在我想在DerivedClass中开发一个使用A和B的方法C.有没有办法可以在DerivedClass中将方法A和B重写为私有,这样只有方法C才会暴露给想要使用我的DerivedClass的人?
Bri*_*ndy 70
这不可能,为什么?
在C#中,强制要求你如果继承了公共方法,就必须将它们公之于众.否则他们希望你不要从这个阶段派生出来.
您不必使用is-a关系,而是必须使用has-a关系.
语言设计者不会故意允许这样做,以便您更正确地使用继承.
例如,有人可能会意外地将类Car混淆为从类Engine派生以获得它的功能.但引擎是汽车使用的功能.所以你想要使用has-a关系.Car的用户不希望访问Engine的界面.汽车本身不应该将引擎的方法与它自己的方法混淆.Nor Car的未来派生.
所以他们不允许它保护你免受糟糕的继承层次结构的影响.
你应该怎么做?
相反,你应该实现接口.这使您可以使用has-a关系自由使用功能.
其他语言:
在C++中,您只需在private,public或protected的基类之前指定一个修饰符.这使得基础的所有成员都公开到指定的访问级别.对我来说,你不能在C#中做同样的事情似乎很愚蠢.
重组后的代码:
interface I
{
void C();
}
class BaseClass
{
public void A() { MessageBox.Show("A"); }
public void B() { MessageBox.Show("B"); }
}
class Derived : I
{
public void C()
{
b.A();
b.B();
}
private BaseClass b;
}
Run Code Online (Sandbox Code Playgroud)
我理解上面这些类的名字有点没有实际意义:)
其他建议:
其他人建议将A()和B()公开并抛出异常.但是,这并没有为人们提供友好的课程,而且实际上没有意义.
小智 28
例如,当您尝试从a继承时List<object>,您想要隐藏直接Add(object _ob)成员:
// the only way to hide
[Obsolete("This is not supported in this class.", true)]
public new void Add(object _ob)
{
throw NotImplementedException("Don't use!!");
}
Run Code Online (Sandbox Code Playgroud)
这不是最理想的解决方案,但它可以完成这项工作.Intellisense仍然接受,但在编译时你会收到一个错误:
错误CS0619:'TestConsole.TestClass.Add(TestConsole.TestObject)'已过时:'此类不支持此'.
@Brian R. Bondy 向我推荐了一篇关于通过继承和new关键字隐藏的有趣文章。
http://msdn.microsoft.com/en-us/library/aa691135(VS.71).aspx
因此,作为解决方法,我建议:
class BaseClass
{
public void A()
{
Console.WriteLine("BaseClass.A");
}
public void B()
{
Console.WriteLine("BaseClass.B");
}
}
class DerivedClass : BaseClass
{
new public void A()
{
throw new NotSupportedException();
}
new public void B()
{
throw new NotSupportedException();
}
public void C()
{
base.A();
base.B();
}
}
Run Code Online (Sandbox Code Playgroud)
这样,像这样的代码将抛出NotSupportedException:
DerivedClass d = new DerivedClass();
d.A();
Run Code Online (Sandbox Code Playgroud)
你需要的是组合而不是继承.
class Plane
{
public Fly() { .. }
public string GetPilot() {...}
}
Run Code Online (Sandbox Code Playgroud)
现在,如果您需要一种特殊的平面,例如具有PairOfWings = 2的平面,但平面可以做任何事情.您继承平面.通过这种方式,您声明您的派生符合基类的契约,并且可以替换而不会在期望基类的任何地方闪烁.例如,LogFlight(Plane)将继续使用BiPlane实例.
但是,如果您只需要想要创建的新Bird的Fly行为,并且不愿意支持完整的基类合约,那么您需要编写.在这种情况下,重构方法的行为以重用到新类型的Flight中.现在在Plane和Bird中创建并保持对此类的引用.你没有继承,因为Bird不支持完整的基类契约......(例如它不能提供GetPilot()).
出于同样的原因,您在覆盖时无法降低基类方法的可见性.您可以在派生中覆盖并使基本私有方法公开,但反之亦然.例如,在这个例子中,如果我派生出一种Plane"BadPlane",然后覆盖并"隐藏"GetPilot() - 将其设为私有; 一个客户端方法LogFlight(Plane p)适用于大多数Planes,但如果LogFlight的实现恰好需要/调用GetPilot(),它将会爆炸为"BadPlane".由于预期基类的所有派生都是"可替代的",无论何时需要基类参数,都必须禁止这种派生.
| 归档时间: |
|
| 查看次数: |
41332 次 |
| 最近记录: |