行。我认为我理解new
和override
之间的区别。但是,如果我的理解是正确的,那么关于OOP的原则是不是new
关键字?有了它,我可以在子类中创建一个方法,该方法具有与基类不同的签名,对吧?像这样:
class MyBase
{
public int[] SampleMethod() { ... }
}
class MyChild : MyBase
{
public new string[] SampleMethod() { ... }
}
客户端希望从MyBase
继承的类具有名为SampleMethod
的方法,该方法返回int
数组,但子类不返回。这与override
不同,我认为要求子方法与父级具有相同的签名。我错过了什么?
答案 0 :(得分:5)
问题出在你的陈述中:
客户端希望从MyBase继承的类具有一个名为SampleMethod的方法,该方法返回一个int数组,但子类不返回。
这是不真实的。实际上,类实现了该方法。只是也实现了自己的版本。
如果MyChild
的实例被声明为:
MyBase myBase = new MyChild();
这一行:
int[] ints = myBase.SampleMethod();
有效并调用您期望的方法。相比之下,这一行:
string[] strings = myBase.SampleMethod();
会失败。但是,如果将其强制转换为MyChild
:
string[] strings = ((MyChild)myBase).SampleMethod();
这完全符合您的预期。
这里的要点是,由于变量已知为MyBase
,因此无论您的new
实现如何,它都会完全按照您的预期行事。因此,多态性 - 因为它对编译时类型做出反应 - 不受影响,并且对任何OOP概念都没有任何暗示。
答案 1 :(得分:2)
我认为适用的原则是Liskov Substitution Principle(LSP),我同意你不应该有一个只在继承类中输出类型不同的方法。通常人们会期望实现类与祖先定义的方法具有相同的语义,无论它是从类型为基类还是实现类的变量引用的。
然而,有原则的是,它们是原则,而不是法律,偶尔也可能违反它们。话虽如此,我不记得长时间使用new
关键字来替换父类实现。
我认为需要new
方法作为代码气味 - 暗示我的设计可能有问题。也许我试图在那个类层次结构中做太多,或者我选择了错误的模式来应用。
答案 2 :(得分:0)
在继承的接口对方法或属性有更严格的限制的情况下,我更喜欢使用new
关键字:
class Car
{
}
class Truck : Car
{
}
interface IDriver
{
Car Vehicle { get; }
}
class Driver : IDriver
{
public Car Vehicle { get; }
public Driver(Car vehicle)
{
Vehicle = vehicle;
}
}
interface ITrucker : IDriver
{
new Truck Vehicle { get; }
}
class Trucker : Driver, ITrucker
{
public new Truck Vehicle
{
get { return (Truck) base.Vehicle; }
}
public Trucker(Truck vehicle)
: base(vehicle)
{
}
}
当我得到一个明确的ITrucker
对象时,我直接通过Truck
属性获得了它的Vehicle
,不需要其他强制转换,在某些情况下非常方便。
无论如何,如果允许设置,则需要仔细处理这些属性。否则,人们会很快得到无效的演员表。对于只读属性,这有时非常方便。
答案 3 :(得分:-1)
它主要用于隐藏基本方法。如果您计划隐藏基类的方法,那么在派生类中标记方法的正确方法。如果不使用new关键字,则会收到编译器警告。
如果您没有具有相同签名的基本方法,则在派生类中使用new是没有意义的。