简体   繁体   English

为什么转换为接口而不是转换为类 java?

[英]Why cast to an interface instead of casting to a class java?

I have come across some java classes used in the spring framework.我遇到了一些在 spring 框架中使用的 java 类。 First, there is the beans in the applicationContext.xml首先,applicationContext.xml 中有 bean

<bean id="someBean" parent="txProxyTemplate">
    <property name="target">
        <bean class="path.to.bean.impl.SomeBeanImpl">
            ...
        </bean>
...
</bean>

And I have the interface ISomeBean , and its implementation SomeBeanImpl Then, I have another class which uses ISomeBean.我有接口ISomeBean和它的实现SomeBeanImpl然后,我有另一个使用 ISomeBean 的类。

public class SomeOtherClass {
  ...
    public function doStuff() {
        ...
        ApplicationContext ctx;
        SomeBean theBean = (SomeBean) ctx.getBean; 
   }
}

I want to know why do we cast to an interface instead of casting to the class.我想知道为什么我们要转换到接口而不是转换到类。

Why would you want to tie SomeOtherClass to a specific implementation?为什么要将SomeOtherClass绑定到特定实现? Using the interface, you get loose coupling - you can test against a fake implementation, or switch to a different implementation later.使用该接口,您会获得松散耦合 - 您可以针对假实现进行测试,或者稍后切换到不同的实现。

This is a large part of the benefit of inversion of control - you aren't as tightly coupled to your dependencies as if you instantiate them directly within the class.这是控制反转的很大一部分好处 - 您与依赖项的耦合不像直接在类中实例化它们那样紧密。

The logic behind such type of casting is to give freedom to the Spring IOC and Dependency Injection.这种类型转换背后的逻辑是为 Spring IOC 和依赖注入提供自由。 One of the benefits of using this approach is that the coupling between classes is very loose,使用这种方法的好处之一是类之间的耦合非常松散,

for example in ur case if some fine morning u decide to change the code of ISomeBeanImpl, u don't need to change anything else as long as functionality doesn't change..例如,在您的情况下,如果某个晴朗的早晨您决定更改 ISomeBeanImpl 的代码,则只要功能不更改,您就不需要更改任何其他内容..

Have a look on Spring IOC documentation , the idea will be more clear...看看Spring IOC文档,思路会更清晰...

One great benefit of using dependency injection is that your classes doesn't have to know which implementation is used, only that they need one implementation.使用依赖注入的一大好处是您的类不必知道使用了哪种实现,只需知道它们需要一个实现。 Thereby it makes sence to cast it to an interface.因此,将其转换为接口是有意义的。

You should not however confuse it with what can or can't be done.但是,您不应将其与可以或不可以做什么混淆。

You cast to an interface to keep your code generic and loosely coupled.您可以转换为接口以保持您的代码通用和松散耦合。 Once you cast an object to a concrete class you have added a tight coupling between your object and its collaborator.一旦你将一个对象转换为一个具体的类,你就在你的对象和它的合作者之间添加了一个紧密的耦合。 Should the class type of the collaborator change then your object's cast operation will potentially break - causing a ClassCastException.如果协作者的类类型发生变化,那么您的对象的转换操作可能会中断 - 导致 ClassCastException。 If instead we use an interface you can freely change the implementing class type of the collaborator without worrying about implications on clients.相反,如果我们使用接口,您可以自由更改协作者的实现类类型,而不必担心对客户端的影响。

There is the style-aspect of it - loose coupling and all that.有它的风格方面 - 松散耦合等等。

More concretely: If you are using AOP (which Spring does by default for many built-in functionalities, transactional support for instance) and for instance cglib proxying, the actual bean will not be of the implementation class, it will be aa dynamically created proxy-class.更具体地说:如果您正在使用 AOP(Spring 默认为许多内置功能,例如事务支持)和例如 cglib 代理,则实际的 bean 将不是实现类,它将是一个动态创建的代理-班级。 In that case, your application will fail with all sorts of ClassCast-like exceptions.在这种情况下,您的应用程序将因各种类 ClassCast 异常而失败。 This can come as a nasty surprise down the road if you make changes that inadvertently actives the proxying behaviour in spring.如果您所做的更改在春季无意中激活了代理行为,那么这可能会带来令人讨厌的惊喜。

A dependency injection framework have two goals:依赖注入框架有两个目标:

  1. to manage the lifecycle of object, that is, how they are created.管理对象的生命周期,即它们是如何创建的。
  2. to decouple the code from concrete implementation, that is, you can switch between implementations of an interface without recompiling代码与具体实现解耦,即无需重新编译即可在接口的实现之间切换

If you are not interested in 1 nor 2, obviously you don't need dependency injection: simply create the bean yourself SombeBeanImpl = new SomeBeanImpl() .如果您对 1 或 2 不感兴趣,显然您不需要依赖注入:只需自己创建 bean SombeBeanImpl = new SomeBeanImpl()

If you are interested only in 1 but not 2, you could cast the bean you obtain to SomeBeanImpl , but then you are bound to always use it.如果您只对 1 而不是 2 感兴趣,您可以将您获得的 bean 转换为SomeBeanImpl ,但是您必须始终使用它。 I suspect there is a way to specify in Spring that you are just having one implementation and you don't have an interface, but I'm not sure.我怀疑有一种方法可以在 Spring 中指定您只有一个实现并且没有接口,但我不确定。

If you are interested in 2, you are by definition interested in 1 as well.如果您对 2 感兴趣,那么根据定义,您也对 1 感兴趣。 Indeed, if you don't want to explicitely state what concrete class to instantiate, you delegate that to a factory that control the creation of objects.实际上,如果您不想明确说明要实例化的具体类,则可以将其委托给控制对象创建的工厂 This is what a dependency injection framework actually is, a complex factory.这就是依赖注入框架的真正含义,一个复杂的工厂。

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

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