Java 通过在运行时注入实现多态

Java polymorphism through injection at runtime

听说Java可以通过运行时注入实现多态。有人可以举一个简单的例子来说明这是如何完成的吗?我在网上搜索,但找不到任何东西:也许我搜索错了。所以我通过接口和扩展了解多态性,例如

class MyClass extends Parent implements Naming

在这种情况下,我实现了两次多态性:MyClass 同时属于 ParentNaming 类型。但我不明白注射是如何工作的。这个想法是我不会在注入期间使用 @Override 关键字。我希望问题很清楚。谢谢。

因此,根据我的理解,这里的最终结果是通过注入而不是 @Override 在开发过程中更改方法的行为。

So I know about polymorphism through interface and and extension such as

class MyClass extends Parent implements Naming

这称为继承而非多态性。 MyClass是一个ParentMyClass也是一个Naming。话虽这么说,inheritance 允许您实现 polymorphism

考虑 class 除了 MyClass 还实现 Naming :

class SomeOtherClass implements Naming {
     @Override
     public void someMethodDefinedInTheInterface() {

     }
 }

现在考虑在代码库中的某处采用 Naming 参数的方法:

public void doSomething(Naming naming) {
     naming.someMethodDefinedInTheInterface();
}

doSomething 方法可以传递任何实现 Namingclass 的实例。所以以下两个调用都是有效的:

doSomething(new MyClass());//1
doSomething(new SomeOtherClass());//2

观察如何使用不同的参数调用 doSomething。在运行时,第一次调用将从 MyClass 调用 someMethodDefinedInTheInterface,第二次调用将从 SomeOtherClass 调用 someMethodDefinedInTheInterface。这就是所谓的 runtime-polymorphism,可以通过继承来实现。

But I don't get how injection works. The idea is that I would not be using the @Override keyword during injection

广义上是这样。要将某些东西 inject 变成 class,class 理想情况下应该有利于 composition 而不是 inheritance。请参阅 this 答案,该答案很好地解释了支持组合而不是继承的原因。

为了从我的回答扩展上面的例子,让我们修改 doSomething 方法如下:

  public class ClassHasANaming {
      private Naming naming;

      public ClassHasANaming(Naming naming) {
          this.naming = naming;
      }

      public void doSomething() {
           naming.someMethodDefinedInTheInterface();
      }
  }

观察 ClassHasANaming 现在如何拥有一个 Naming 可以从外部世界 注入 的依赖关系:

ClassHasANaming callMyClass = new ClassHasANaming(new MyClass());
callMyClass.doSomething();

如果您使用 Factory pattern,您实际上可以选择在运行时实例化哪个子class。

您认为我们可以使用 inheritance 完成上述操作吗?

 public class ClassIsANaming implements Naming {
    public void doSomething() {
        someMethodDefinedInTheInterface();
    }

    @Override
    public void someMethodDefinedInTheInterface() {
        //....
    }
 }

答案是ClassIsANaming 在编译时本身绑定到 someMethodDefinedInTheInterface 方法的单个实现。 `

举个人为的例子。你有一个 class Store 存储东西:

class Store {

    private List l

    void store(Object o) {
       l.add(o);
    }

    void setStoreProvider(List l) {
        this.l = l
    }
}

您可以使用 setStoreProvider 注入用作后备存储的实际 List,它可以是链表、数组后备列表等。

因此,根据注入类型,您的 Store class 将具有注入类型的特性(关于内存使用、速度等)。

这是一种没有class实现接口的多态。