2014-07-16 44 views
11

我有一个抽象基类:为什么我可以抽象重写一个抽象方法?

abstract class Foo 
{ 
    virtual void DoSomeStuff() 
    { 
     //Do Some Stuff 
    } 

    abstract void DoSomeCrazyStuff(); 
} 

,并从该派生出的另一抽象类:

abstract class Bar : Foo 
{ 
    abstract override void DoSomeStuff(); 

    abstract override void DoSomeCrazyStuff(); 
} 

我明白你为什么会想抽象覆盖DoSomeStuff() - 这将需要一个新的实现进一步派生类。但我无法弄清楚为什么你想抽象覆盖DoSomeCrazyStuff()。据我所知,这是多余的 - 我很确定删除它将不会产生负面影响。

是否存在一些抽象重写对抽象操作有用的用例?如果没有,为什么没有编译器警告,告诉我我写的内容什么都不做?

+1

这个链接可以帮助 - “因为规范是这么说的” http://msdn.microsoft.com/en-us/library/ms173150%28VS.80%29.aspx – terrybozzio

+3

此落在范畴 –

+0

看起来像是Roslyn的一个很好的功能请求。 –

回答

3

为什么我可以抽象重写一个抽象方法?

对于初学者来说,没有防止它的实际原因。如果它产生了一个编译器错误,那么所做的只是让类变得更脆弱。例如:

abstract class Foo 
{ 
    virtual void DoSomeStuff() 
    { 
     //Do Some Stuff 
    } 
} 

abstract class Bar : Foo 
{ 
    abstract override void DoSomeStuff(); 
} 

如果抽象抽象的覆盖是非法的,在Foo上改变DoSomeStuff抽象现在会阻止从酒吧编译。抽象覆盖是多余的,但没有潜在的负面影响,所以编译器可以做到这一点。


为什么没有一个编译器警告,通知我说什么,我已经写了什么也不做?

编译器生成的警告对于表示风险某些事情:非显式方法隐藏,无法访问的代码,使用过时的方法等的唯一的“问题”的不必要的抽象倍率可指示的是,代码是不能有效地书面。这不是编译器关心的问题。


是否存在这样一种抽象的抽象的覆盖做一些有用的一些使用情况?

没有功能。但是,有几种用例可能会故意这样做:

  • 提高代码的“可读性”。具有冗余抽象覆盖将提醒该方法是抽象的。
  • 如果未来对基类的更改包括提供虚拟实现,则可以预先阻止某些类访问该基类。
  • 如果抽象重写是多余的,因为基类已从虚拟实现更改为抽象,它可以安全地放置。
2

通过明确abstract overrideBar荷兰国际集团它,你要确保它会通过Bar的后裔们被看作是抽象的,即使在Foo将来可能会变成一个非抽象之一。尽管有这样的变化,Bar的后代将与同样的合同工作。

+0

我看到了这方面的实用价值,但这不是对Liskov Substitution的违反吗?任何对'Foo'进行操作并期待具体的'DoSomeCrazyStuff'的方法在传递一个'Bar'时会中断。 –

+2

@AustinMullins Bar和DoSomeCrazyStuff仍然是抽象的,所以没有什么会在Bar上运行,而是一个具体的类,如果没有实现所有的抽象方法就不能编译。 – User

+0

@OndrejTucny您不需要额外的抽象覆盖来防止合同更改,现有的'Bar'覆盖仍然会覆盖虚拟实现。它是先发制人地阻止'Bar'的后代被写入''Foo's被更改为虚拟的访问基础实现。为什么要阻止访问尚未写入的方法?为什么不保存该决定,直到方法实际写入? – User

相关问题