2013-12-18 56 views
1

什么是真正的实际使用'new' modifier的?成员隐藏,什么是它的实际用途

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 

这是否打破了里氏替换原则?

干杯。

+2

法律可以被打破或弯曲时,他们满足现实世界 - http://en.wikipedia.org/wiki/Circle-ellipse_problem – Kami

回答

2

关于LSP

这不破LSP。 的LSP指出,如果DerivedBase子类型,则根据Base任何码(例如,具有Base参数的方法,像void DoSomething(Base b))可以与的Derived实例替换,而没有任何令人惊讶的效果。

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

这是预期的行为,因为Say不虚。这意味着书面反对Base变量的代码,预计Base执行被调用。

实用目的

你能想到的new方法,以此来规避非重写的方法 - 用一个警告!您必须针对该特定类型进行编程 - 而不是其接口。

1

虽然这不是一个好的做法,以做到这一点,我可以看到它是有用的,当你从一个第三方组件继承(即代码,你就不用管了),你希望有一个方法,不同的行为。

+0

但你*不*覆盖的方法之一,当你做这个。这是有点点。 – Servy

+0

我不是说覆盖关键字,但有不同的行为。我会更新答案... –

+1

我不是在谈论关键字覆盖,而是在概念。你回答同样的问题,因为你正在接受同样的概念。如果该方法是虚拟的,并且您覆盖它,那么您确实正在有效地更改该方法的实现。从概念的角度来看,隐藏你只是创建一个全新的方法(因此使用'new'关键字),并明确地*不*改变现有的方法。它仍然存在,完全没有改变。 – Servy

1

在派生类的方法被认为是它的基类“相关”的方法,如果它具有相同的名称和参数列表。编译器设计人员处理此类相关的方法有两种方法:

  1. 依靠惯例 - 例如,他们可以宣布这种方法的重写; Java这样做。从程序员
  2. 请求明确方向 - C#设计了这条路线:他们要求程序员指定与virtual/override相关的方法,并与new无关的方法。

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

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

这是否打破了里氏替换原则?

可以说,它没有的事实:在派生类中已经推出了具有相同的名称和参数,程序员明确指定为无关基座中的方法的方法,在行为并不能改变什么在派生类用作其基类的替代品的情况下。

1

它简单地允许用户重新定义的基类的方法。当然,有预见这个偶然的开发者,你会希望他们不得不编码它作为虚拟(对于一个默认的实现)或抽象的(其中任何实现需要指定)。

的LSP简单地把刚需要一个基类,子类可以互换使用,所以这不违反原则,据我可以看到。

的C#甲小缺点是,只有一个类可以继承这样的情况下,例如这应该是复杂的系统,其中所述多个执行的接口将是优选的比较少见。

1

DerivedBase和客户端都在你的控制这可能是有用的。假设你从此开始。

 

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(); 
    } 
} 
 
相关问题