简体   繁体   English

抽象类优于接口的优点

[英]Advantage of abstract class over interface

I got the following statement from an MSDN article . 我从MSDN文章中得到以下声明。 It says that the abstract classes have an advantage over interfaces because it is possible to alter an abstract class to add new members. 它说抽象类比接口有优势,因为可以改变抽象类来添加新成员。 Doesn't altering the abstract class really make the classes inheriting from it unstable? 不改变抽象类真的会使从它继承的类不稳定吗? Or can any one please explain what is their point here? 或者任何人都可以解释一下他们的观点是什么?

Do favor defining classes over interfaces. 支持在接口上定义类。

In later versions of your library, you can safely add new members to classes; 在库的更高版本中,您可以安全地向类添加新成员; you cannot add members to interfaces without breaking existing code. 您不能在不破坏现有代码的情况下向接口添加成员。

Say you have an interface 假设你有一个界面

public interface Animal 
{
     void Sleep();
}

you release your library and you find out you need to add a property to the interface. 你发布你的库,你发现你需要添加一个属性到界面。

public interface Animal 
{
     int Age{get;set;}
     void Sleep();
}

All the code that every one wrote against the first version of the interface would no longer compile forcing an upgrade. 每个人对第一个版本的接口编写的所有代码都不再编译强制升级。 If you released the first version with this abstract class. 如果您使用此抽象类发布了第一个版本。

public abstract class Animal 
{
    public abstract  void Sleep();
} 

Now you need to add another property 现在您需要添加另一个属性

public abstract class Animal
{
    public virtual int Age{get;set;}
    public abstract  void Sleep();
} 

In this case there is no need for users to change there code. 在这种情况下,用户无需更改代码。

Assume that you writing code and use some interface ( IExample ) in a first version. 假设您编写代码并在第一个版本中使用某个接口( IExample )。 In the second version of your program you understand that IExample should have a method called IExample.NewMethod . 在程序的第二个版本中,您了解IExample应该有一个名为IExample.NewMethod的方法。 If you extend IExample with this method, automatically all code you wrote before will be broken because all classes which inherited from IExample will be not implement this interface completely - so code will not be compiled. 如果使用此方法扩展IExample ,则会自动IExample之前编写的所有代码,因为从IExample继承的所有类都不会完全实现此接口 - 因此代码将不会被编译。 It's correct if we talking about this case only. 如果我们只讨论这个案子,这是正确的。 This problem could be fixed with using new interface ( INewExample ) inherited from IExample , or just creating new interface without inheritance 使用从IExample继承的新接口( INewExample )或仅创建没有继承的新接口可以解决此问题

But interface have some advantages for abstract class also. 但是界面对抽象类也有一些优势。 Interfaces encapsulated realization of your code much better than abstract classes. 接口封装了代码的实现比抽象类更好。 Also you could use interfaces for different classes, but when you use abstract classes it should means that your class is abstract class somehow (for example Circle is a Shape so you can inherit Circle from abstract Shape ) but it really bad idea to inherit Circle from Car for example even if they have the same interface 你也可以使用不同类的接口,但是当你使用抽象类时,它应该意味着你的类在某种程度上是抽象类(例如, Circle是一个Shape所以你可以从抽象的Shape继承Circle )但是继承Circle是非常不好的主意。 Car为例,即使它们具有相同的界面

To read complete overview of interface VS abstract classes I advice you Kent Beck's book and Code Complete for inheritance in general 要阅读界面VS抽象类的完整概述,我建议您使用Kent Beck的书和一般的继承代码完成

It's not to be taken too strictly. 不要太严格。 Programming through interfaces (as contracts) is really the best way to decouple your application. 通过接口编程(作为契约)实际上是解耦应用程序的最佳方法。 For example, creating a wrapper around an interface is very easy, while a class doesn't even have to have a single virtual method. 例如,在界面周围创建包装器非常容易,而类甚至不必只有一个虚拟方法。

Additionally, the article doesn't even seem to compare abstract classes to interfaces (because it only mentions them in the next "guideline"), but all classes in general over interfaces. 此外, 该文章似乎甚至没有将abstract类与接口进行比较(因为它只在下一个“指南”中提到它们),而是所有类通常都在接口上。 So, it's a rather fuzzy guideline, if you ask me. 所以,如果你问我,这是一个相当模糊的指导方针。

It might make sense exclusively with the problem stated: changing an interface breaks all implementations, while adding members to a class doesn't. 它可能仅对所述问题有意义:更改接口会破坏所有实现,而添加成员则不会。 On the other hand, if you change a method's signature, you won't be very lucky with classes either. 另一方面,如果你改变一个方法的签名,你也不会很幸运。 From a security point of view, abstract classes do provide a way to make sure that your library always exposes its own functionality to callers, allowing modifications only where you want them. 从安全的角度来看,抽象类确实提供了一种方法来确保您的库始终向调用者公开其自己的功能,只允许在您需要的地方进行修改。 With interfaces, you can pass pretty much any code which satisfies the contract. 使用接口,您可以传递几乎任何满足合同的代码。

The biggest advantage of Abstract class is a possibility to have internal members, where Interface can not have. Abstract类的最大优点是可以拥有内部成员, Interface不能拥有。 On other part, you can have a multiinheritance on interfaces , but on absrtact classes not. 另一方面,您可以在interfaces上使用多absrtact ,但不能在absrtact类上使用。

the advantage of an abstract class is that you can implement common functionality. 抽象类的优点是可以实现常用功能。 with an interface, each implementing class has to provide its own implementation of the defined operations. 使用接口,每个实现类都必须提供自己定义的操作的实现。

Doesn't altering the abstract class really make the classes inheriting from it unstable? 不改变抽象类真的会使从它继承的类不稳定吗?

Not necessarily. 不必要。 As long as you don't mark your new members as virtual , any class that currently doesn't use the new members will be able to ignore them, so there is no versioning break. 只要您不将新成员标记为virtual成员,任何当前不使用新成员的类都将能够忽略它们,因此没有版本控制中断。

or can any one please explain what is their point here? 或者任何人都可以解释一下他们的观点是什么?

The point is that, if you add a new member to an interface, any class that implements that interface is immediately broken because it doesn't implement the new member. 关键是,如果向接口添加新成员,则实现该接口的任何类都会立即被破坏,因为它没有实现新成员。 There is no such build break for adding a member to an abstract class. 将成员添加到抽象类没有这样的构建中断。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM