简体   繁体   English

Spring为什么用接口代替抽象类?

[英]Spring Why Interfaces instead Abstract Classes?

Sometimes,we use Spring in some automatic way. 有时,我们以某种自动方式使用Spring。 Today i was thinking and searching the followig. 今天我正在思考和寻找追随者。

Why we use to do this in Spring? 为什么我们在春季使用此功能? @Autowired IAnimal animal; @Autowired IAnimal动物;

And why we usually dont do something like this? 为什么我们通常不这样做? @Autowired Animal animal; @Autowired Animal动物;

Animal is an abstract class,and in our beans.xml ,or using @Autowired with Qualifier,we can specify which implementation we want.A Dog,a Cat,etc. Animal是一个抽象类,在我们的beans.xml中,或者通过将@Autowired与Qualifier配合使用,我们可以指定所需的实现,如Dog,Cat等。

I know i am wrong,but i would like some explanation about the cons of the Abstract Class approach instead of Interfaces approach. 我知道我错了,但是我想对一些抽象类方法而不是接口方法的缺点做一些解释。

Now,if we want to inject some ORM implementation,Ibatis or Hibernate,it makes more sense to use interfaces injection,because both providers dot not share an abstract class,but they share same Interface.But any other example? 现在,如果我们要注入一些ORM实现(Ibatis或Hibernate),则使用接口注入更有意义,因为两个提供程序都不共享抽象类,而是共享相同的Interface。但是还有其他示例吗?

Thanks in advance! 提前致谢!

In the early Spring versions, declaring an interface could be mandatory to make the bean working with some features that required proxy class generation via interface. 在早期的Spring版本中,必须声明接口才能使Bean使用某些需要通过接口生成代理类的功能。
Recent Spring versions don't have any more this restriction. 最新的Spring版本没有此限制。 So now, in Spring (as without Spring) a shared good practice is to make a bean class implement an interface only if it makes sense : KISS (Keep it simple and stupid) principle. 因此,现在,在Spring(与没有Spring一样)中,一个共同的良好实践是仅在有意义的情况下使Bean类实现接口:KISS(保持简单和愚蠢)原理。
Abstraction has a cost and we want to accept it only for good reasons. 抽象是有代价的,我们仅出于充分的理由才愿意接受。

The main advantage of an interface is multiple inheritance. 接口的主要优点是多重继承。 Java does not allow you to extend multiple classes, and there are sensible reasons for this. Java不允许您扩展多个类,这是有道理的。 Some languages allow this (eg C++ and others) and there are reasons why it can be useful, but Java doesn't. 某些语言(例如C ++和其他语言)允许这样做,并且有一定的原因使它有用,但Java却没有。

However, you can implement multiple interfaces. 但是,您可以实现多个接口。 There is also a more subtle point about what an interface really is vs. what a abstract class is. 关于接口真正什么和抽象类是什么还有一个更微妙的问题。

If you have class MyClass extends MyAbstractClass , you are effectively saying "all instances of MyClass are instances of MyAbstractClass ". 如果您拥有class MyClass extends MyAbstractClass ,那么您实际上是在说“所有MyClass实例都是MyAbstractClass实例”。 This applies to most common metaphors applied to OOP. 这适用于应用于OOP的最常见的隐喻。 For example, all Dogs are in fact Animals. 例如,所有的狗实际上都是动物。

However, an interface just defines some behaviour. 但是,接口仅定义了一些行为。 In a lot of programming contexts, it makes more sense to define things by what they can do , rather than what they are . 在许多编程环境中,通过事物可以做 什么而不是事物来定义事物更有意义。 Eg A Dog is a Barkable, Runnable, Walkable, Feedable, etc... Here you are defining what it can do. 例如,狗是可吠叫,可奔跑,可步行,可喂食的……在这里,您定义它可以做什么。

With your Spring example, you probably don't care that the object you are working with is actually an Animal, you probably just care that it can do all the things Animals can do. 在您的Spring示例中,您可能并不在乎所使用的对象实际上是动物,您可能只是在乎它可以完成动物可以做的所有事情 That is a major reason why interfaces are preferred. 这就是为什么首选接口的主要原因。

It really depends on your project. 这确实取决于您的项目。

You want to use an interface ( IAnimal ) in cases where you may have multiple implementations of such interface and you are going to decide which one to use during packaging. 如果您可能要使用一个接口( IAnimal )来实现该接口的多种实现,并且要决定在打包过程中使用哪个接口,则需要使用该接口。

For example, let's say that implementations on IAnimal need to be different based on whether you are under Windows or Linux, during packaging you may want to prepare two different versions of your application (one for Windows and one for Linux) and each package will contain only the code meant for that platform. 例如,假设您是在Windows还是Linux下, IAnimal上的实现IAnimal需要不同,在打包过程中,您可能需要准备两种不同版本的应用程序(一个用于Windows,一个用于Linux),并且每个软件包都包含仅适用于该平台的代码。 In such case, in one package you will include the implementation for Windows and in the other case the implementation for Linux. 在这种情况下,将在一个软件包中包含Windows的实现,而在另一个软件包中将包含Linux的实现。

Another common scenario is teams working as "black boxes" with one team needing the dependency of another team. 另一种常见的情况是团队充当“黑匣子”,其中一个团队需要另一团队的依赖。 In that case all that is agreed between the teams is the "contract" of the implementation (that is: the interface). 在这种情况下,团队之间达成的所有协议就是实施的“合同”(即:接口)。 Your team will be able to work against a "mock" implementation built by you while the other team develops the one that will eventually be released. 您的团队将能够与您自己构建的“模拟”实现抗衡,而另一团队则开发最终将被发布的实现。

Otherwise, the general advice is to "keep it simple" and add the interface only if it's demonstrated that it's needed. 否则,一般建议是“保持简单”并仅在证明需要时添加接口。 Not doing so will result in much more code than necessary, which will only make everybody's life difficult. 不这样做将导致不必要的代码过多,这只会使每个人的生活变得困难。

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

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