简体   繁体   English

Java:多态调用超级实现

[英]Java: polymorphically call super implementation

Suppose I have this:假设我有这个:

public class A { 
  public String foo() { return "A"; } 
}

public class B extends A { 
  public String foo() { return "B"; } 
  public String superFoo() { return super.foo(); }
}

public class C extends B { 
  public String foo() { return "C"; } 
}

Here, new C().superFoo() returns "A" .在这里, new C().superFoo()返回"A" Is there a way I can polymorphically make new C().superFoo() invoke B.foo() (and hence return "B" ) without the need to override superFoo() in C ?有没有一种方法可以多态地使new C().superFoo()调用B.foo() (并因此返回"B" )而无需覆盖 C 中的C superFoo() I tried with reflection (redefining B.superFoo() like this: return getClass().getSuperclass().getDeclaredMethod("foo").invoke(this) ), hoping that with getDeclaredMethod I could reference the exact method implementation in superclass, but I get "C" in that case (hence, polymorphism is applied).我尝试了反射(像这样重新定义B.superFoo()return getClass().getSuperclass().getDeclaredMethod("foo").invoke(this) ),希望通过getDeclaredMethod我可以引用超类中的确切方法实现,但在那种情况下我得到"C" (因此,应用了多态性)。

I was searching for a solution that doesn't require me to redeclare superFoo() whenever I add a new subclass to the hierarchy.我正在寻找一种解决方案,每当我向层次结构中添加新的子类时,我都不需要重新声明superFoo()

TL;DR TL;博士

Going through the question and comments, it seems like the ask here is to incrementally build up on a behavior.通过问题和评论,这里的问题似乎是逐步建立一种行为。 Taking a different perspective, I would prefer Composition over Inheritance in this scenario.从不同的角度来看,在这种情况下,我更喜欢组合而不是 Inheritance

You can use Decorator pattern and compose the instances together;您可以使用装饰器模式并将实例组合在一起; which in turn gives you a reference to the parent's foo() implementation.这反过来又为您提供了对父级的foo()实现的引用。 One of the other benefits is that you can extend/change the behavior at runtime, which is not possible with a static inheritance design.其他好处之一是您可以在运行时扩展/更改行为,这对于 static inheritance 设计是不可能的。


About Decorator Pattern关于装饰器模式

Decorator pattern can be used to attach additional responsibilities to an object either statically or dynamically.装饰器模式可用于静态或动态地将附加职责附加到 object。

  • Component - Interface for objects that can have responsibilities added to them dynamically. Component - 可以动态添加职责的对象的接口。
  • ConcreteComponent - Defines an object to which additional responsibilities can be added. ConcreteComponent - 定义一个 object 可以添加额外的职责。
  • Decorator - Maintains a reference to a Component object and defines an interface that conforms to Component's interface. Decorator - 维护对组件 object 的引用并定义符合组件接口的接口。
  • Concrete Decorators - Concrete Decorators extend the functionality of the component by adding state or adding behavior. Concrete Decorators - Concrete Decorators 通过添加 state 或添加行为来扩展组件的功能。

在此处输入图像描述

Sample Code示例代码

Let's take a Pizza baking process as an example.让我们以披萨烘焙过程为例。

Component interface - Defines the contract that a Pizza must be baked. Component接口 - 定义必须烘焙比萨的合同。

public interface Pizza {
    void bake();
}

ConcreteComponent class - This is your implementation of the interface which can stand alone by itself. ConcreteComponent class - 这是您可以独立实现的接口的实现。 It should not extend the Decorator and it appears at the innermost position when the objects are composed together (see client code at the end)它不应该扩展Decorator ,并且当对象组合在一起时它出现在最里面的 position (见最后的客户端代码)

public class VeggiePizza implements Pizza {
    @Override
    public void bake() {
        System.out.println("I'm a Veggie Pizza in the making :)");
    }
}

Decorator - Specifies a contract for extending the functionality of the ConcreteComponent . Decorator - 指定用于扩展ConcreteComponent功能的合同。

public abstract class Topping implements Pizza {

    private Pizza pizza;

    public Topping(Pizza pizza) {
        this.pizza = pizza;
    }

    @Override
    public void bake() {
        pizza.bake();
    }
}

Concrete Decorator - These implementations add to the functionality of the ConcreteComponent by nesting their constructors together (one of the ways to compose.), The concrete decorator can appear anywhere while composing. Concrete Decorator - 这些实现通过将它们的构造函数嵌套在一起(组合方式之一)添加到ConcreteComponent的功能,具体装饰器可以在组合时出现在任何地方。 except for the innermost position (see client code below).除了最里面的 position(参见下面的客户端代码)。

Here we are defining two toppings - Mushroom and Jalapeno.在这里,我们定义了两种配料——蘑菇和墨西哥胡椒。

public class Mushroom extends Topping {

     public Mushroom(Pizza pizza) {
         super(pizza);
     }

    @Override
    public void bake() {
         addMushroom();
         super.bake();
    }

    private void addMushroom() {
         System.out.println("Adding mushrooms...");
    }
}

public class Jalapeno extends Topping {

    public Jalapeno(Pizza pizza) {
        super(pizza);
    }

    @Override
    public void bake() {
        addJalapenos();
        super.bake();
    }

    private void addJalapenos() {
        System.out.println("Adding jalapenos...");
    }

}

Client code - How do you compose the ConcreteDecorator and ConcreteComponent together?客户端代码- 你如何将ConcreteDecoratorConcreteComponent组合在一起?

public void bakePizza() {
    Pizza pizza = new Mushroom(new Jalapeno(new VeggiePizza()));
    pizza.bake();
}

Notice that we build upon the VeggiePizza by wrapping the objects around with additional behavior from Mushroom and Jalapeno .请注意,我们通过使用MushroomJalapeno的附加行为将对象包裹在VeggiePizza的基础上。 Here, the ConcreteComponent is the innermost VeggiePizza , while our ConcreteDecorator s are Jalapeno and Mushroom .在这里, ConcreteComponent是最里面的VeggiePizza ,而我们的ConcreteDecoratorJalapenoMushroom

Note: Constructor composition is only one of the ways to compose.注意:构造函数组合只是组合方式中的一种。 You can compose object together via setters or use a Dependency Injection framework.您可以通过设置器或使用依赖注入框架将 object 组合在一起。

Output Output

Adding mushrooms...
Adding jalapenos...
I'm a Veggie Pizza in the making :)

Following will return B though I've omitted various safety features for the sake of brevity and used commons-lang because you don't want to have to do this stuff yourself, At a minimum, this code assumes every class defines foo() and the you never directly call a.superFoo()!以下将返回B尽管为了简洁起见我省略了各种安全功能并使用了commons-lang因为您不想自己做这些事情,至少,此代码假定每个 class 定义foo()和你永远不会直接调用a.superFoo()! :) :)

    public String superFoo() {
      return superXXX("foo");
    }

    private <T> T superXXX(String name, Object... args) {
      Method overriddenMethod = MethodUtils.getAccessibleMethod(getClass(), name);
      Iterator<Method> methods = MethodUtils.getOverrideHierarchy(overriddenMethod, EXCLUDE).iterator();
      methods.next(); // this is C
      Method parentMethod = methods.next(); // This is B;

      try {
        return (T)parentMethod.invoke(this, args);
      } catch (Exception e) {
        throw new RuntimeException(e);
      }
    }

FYI.供参考。 There may well be an AspectJ/Javassist/Bytebuddy style solution possible as well whereby you can reimplement the superFoo method on all children of A to be super.foo()也可能有一个 AspectJ/Javassist/Bytebuddy 样式的解决方案,您可以在A的所有子级上重新实现superFoo方法为super.foo()

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

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