1

“新”修饰符的实际实际用途是什么?

public class Base
{
    public void Say()
    {
        Console.WriteLine("Base");
    }
}

public class Derived:Base
{
    public new void Say()
    {
        Console.WriteLine("Derived");
    }
}

如果这只是无法编译,那不是更好吗?这段代码:

        Derived d = new Derived();
        d.Say();
        ((Base)d).Say();

退货

 Derived
 Base

这不违反里氏替换原则吗?

干杯。

4

5 回答 5

2

关于 LSP

这不会破坏 LSP。LSP 声明如果Derived是 的子类型Base,则任何依赖于Base(例如,带有Base参数的方法,如void DoSomething(Base b))的代码都可以替换为 的实例Derived,而不会产生任何令人惊讶的效果。

正如您所指出的,如果您将实例分配给Derived变量BaseBase则将调用实现。

这是预期的行为,因为Say它不是虚拟的。这意味着针对Base变量编写的代码期望Base调用实现。

实用目的

您可以将new方法视为一种规避不可覆盖方法的方法 - 需要注意的是!您必须针对该特定类型进行编程 - 而不是它的接口。

于 2013-12-18T11:16:17.800 回答
1

虽然这样做不是一个好习惯,但当您从第三方程序集(即您无法控制的代码)继承并且您希望方法具有不同的行为时,我可以看到它很有用。

于 2013-12-18T11:16:43.027 回答
1

如果派生类中的方法具有相同的名称和参数列表,则认为派生类中的方法与其基类中的方法“相关”。编译器设计者有两种处理此类相关方法的方法:

  1. 依赖一个约定——例如,他们可以将这些方法声明为覆盖;Java 就是这样做的。
  2. 向程序员请求明确的指导——C # 设计者采用了这条路线:他们要求程序员用virtual/指定相关方法override,用new.

处理相关方法的第一种方法让程序员别无选择:如果他们想要一个不相关的方法,他们必须给它一个不同的名称。第二种方式将选择权留给了程序员,代价是更加冗长。

本质上,new关键字让您可以与编译器沟通,您添加的方法与基类中具有相同名称和参数的方法无关。

这不违反里氏替换原则吗?

可以说,它没有:派生类引入了具有相同名称和参数的方法,程序员明确指定为与基类中的方法无关,这一事实不会改变派生类在某些情况下的行为当它被用作其基类的替身时。

于 2013-12-18T11:19:41.047 回答
1

它只是允许用户重新定义基类中的方法。自然,如果开发人员预见到这种情况,您会希望他们将其编码为虚拟(用于默认实现)或抽象(需要指定任何实现)。

LSP 简单地说只是要求基类和子类可以互换使用,因此据我所知,这并不违反原则。

C# 的一个缺点是只能继承一个类,因此对于首选接口的多个实现的复杂系统来说,这样的情况应该是相对少见的。

于 2013-12-18T11:42:33.780 回答
1

Base当您的客户无法控制时,这可能很有用Derived。假设你从这个开始。


public class Base
{
  // there is no Say method in Base!
}

public class Derived:Base
{
    public /*new*/ void Say() // we don't need new here
    {
        Console.WriteLine("Derived");
    }
}

然后有一天那些负责的人在那里Base添加了很酷的Say方法。您可以重命名Derived.Say,但您无法更改的代码已经在其他地方使用了它。所以你使用new来避免在Derived.


public class Base
{
    public void Say()
    {
        Console.WriteLine("Base");
    }
}

public class Derived:Base
{
    public new void Say()
    {
        Console.WriteLine("Derived");
    }
}

public class SomeClient
{
    public void Run()
    {
        var d = new Derived();
        d.Say();
    }
}

于 2013-12-18T15:40:10.167 回答