“new”关键字(用于方法)和OOP

问题描述 投票:3回答:4

好。我想我理解newoverride之间的区别。但是,如果我的理解是正确的,是不是new关键字反对OOP的原则?有了它,我可以在子类中创建一个方法,该方法具有与基类不同的签名,对吧?像这样:

class MyBase
{
    public int[] SampleMethod() { ... }
}

class MyChild : MyBase
{
    public new string[] SampleMethod() { ... }
}

客户端期望从MyBase继承的类具有名为SampleMethod的方法,该方法返回int数组,但子类不返回。这与override不同,我认为这要求子方法与父级具有相同的签名。我错过了什么?

c# oop inheritance override
4个回答
2
投票

我认为适用的原则是Liskov Substitution Principle(LSP),我同意你不应该有一个只在继承类中输出类型不同的方法。通常,人们会期望实现类与祖先定义的方法具有相同的语义,无论它是从类型为基类还是实现类的变量引用的。

然而,有原则的是,它们是原则,而不是法律,偶尔也可能违反它们。话虽如此,我不记得长时间使用new关键字来替换父类实现。

我认为需要使用new方法作为代码气味 - 暗示我的设计可能有问题。也许我试图在那个类层次结构中做太多,或者我选择了错误的模式来应用。


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概念都没有任何暗示。


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并且不需要另一个强制转换,这在某些情况下非常方便。

无论如何,如果允许设置,这需要仔细处理这些属性。否则可以快速获得无效的演员阵容。对于readonly-Properties,这有时非常方便。


-1
投票

它基本上用于隐藏基本方法。如果您计划隐藏基类的方法,那么在派生类中标记方法的正确方法。如果不使用new关键字,则会收到编译器警告。

如果您没有具有相同签名的基本方法,则在派生类中使用new是没有意义的。

© www.soinside.com 2019 - 2024. All rights reserved.