在一个超类的实例对象中使用子类的方法

3

假设有一个我经常使用并且由方法返回的类。

CommonClass obj = getCommonObject();

现在我想扩展这个类,创建一些实用工具方法以避免重复。
public CommonClassPlus extends CommonClass {

    public String dontRepeatYourself() {
        // the reason I'm creating a subclass
    }
}

当然,我想使用我改进后的类来实现上述方法,但是向下转换是不允许的。
CommonClassPlus obj = getCommonObject(); 
//Cannot cast to CommonClassPlus

如果我只能使用超类的实例对象,如何使用方法dontRepeatYourself()呢?

CommonClassgetCommonObject()来自外部库,我无法改变它们。


请展示getCommonObject()的实现/声明。 - mreiterer
2个回答

3

在Java中,你不能像JavaScript那样为现有实例添加行为。

你可以使用装饰器模式来实现类似的效果:

CommonClassPlus obj = decorate(getCommonObject());

其中decorate()

public CommonClassPlus decorate(CommonClass x) {
  return new CommonClassPlus(x);
}

这种方法可能会产生大量的样板代码,因为它必须将每个方法调用委托给被包装的实例。如果CommonClass中的方法是final的,并且没有接口可以重新实现,则此方法完全失败。

在大多数情况下,您可以使用一个简单的静态帮助器方法来解决问题:

public static String dontRepeatYourself(CommonClass x) {
   ...
}

使用静态方法实际上解决了这个问题。非常感谢,这样更容易了。 - frostbite

2
如果CommonClass来自外部库,您可能希望使用适配器模式将其包装起来,无论如何都要使用组合优于继承的原则。
这样做可以让您完全控制,例如更改您正在使用的库,并允许您添加像dontRepeatYourself()这样的功能。
public class CommonClassAdapter implements MyAdapter {
    private final CommonClass common;
    private final String cachedResult;

    // Note that I'm doing dependency injection here
    public CommonClassAdapter(CommonClass common) {
        this.common = common;

        // Don't expose these because they shouldn't be called more than once
        common.methodIOnlyCallOnce();
        cachedResult = common.anotherMethodIOnlyCallOnce();
    }

    @Override
    public void someMethod() {
        common.someMethodWithDifferentName();
    }

    @Override
    public String dontRepeatYourself() {
        return cachedResult;
    }
}

请注意,大多数现代 IDE 都拥有像 Eclipse 的 Source -> Generate Delegate Methods 这样的功能,可以加快此过程。

我将其标记为正确,因为它提供了一个好的解决方案来回答问题,即使我最终使用了下面建议的更简单的方法。 - frostbite
@user2730785 我同意另一个答案在现有代码中实现起来更快。然而,我认为你从长远来看会更满意这个答案。 - durron597

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接