Python中的多重继承;如何在Java中实现?

1 投票
8 回答
508 浏览
提问于 2025-04-16 09:14

我正在把一些Python代码移植到Java,但遇到了一个问题:

我有一些类需要具备能力A、B或C。类1需要能力A,类2需要A、B和C,而类3需要B和C。最重要的是,我希望将来能轻松地更改哪个类可以拥有哪个能力。

在Python中,我通过多重继承很容易解决了这个问题。但在Java中,我找不到同样好的解决方案。我知道多重继承不太被推荐,所以希望能学到更好的方法。

谢谢!

8 个回答

1

你可以很简单地使用AspectJ的混入语法来模拟多重继承(而且是在编译时就能做到)。首先,声明一个接口,用来定义你想要混入的功能:

public interface A{
    String getSomethingForA();
}

接着,定义一个注解,用来表示你想把这个混入应用到某个类上:

public @interface WithA {}

然后,把这个注解加到你想使用的类上:

@WithA
public class MyClass {}

接下来,实际上要添加一些功能:

@Aspect
public class MixinA {
    public static class AImpl implements A{
        public String getSomethingForA() {
            return "it worked!";
        } 
    }

    @DeclareMixin("@WithA *")
    public static A get() {
        return new AImpl();
    }
}

你需要使用aspectj的jar包,并在编译过程中运行这些方面的代码,但这样可以让你创建真正模块化的功能,然后再强制把它们合并到你的类中。要访问带有新功能的类,可以这样做:

MyClass obj = new MyClass();
((A)obj).getSomethingForA();

你可以把同样的注解应用到另一个类上,并进行类型转换:

@WithA
@WithB //let's pretend we created this with some other functionality
public class AnotherClass {}

AnotherClass anotherObj = new AnotherClass();
((A)anotherObj).getSomethingForA();
((B)anotherObj).andSetSomethingElseForB("something else");
3

多重继承并不是个坏事。真正被人们诟病的是“实现继承”(也就是“代码重用”),因为它会导致一个叫做“钻石问题”的难题。而且,实际上,代码重用和面向对象编程(OO)并没有太大关系。

你想做的事情可以通过多重继承来解决(如果需要“代码重用”,可以考虑使用委托)。

interface A {

    void move();

}

interface B {

    void eat();

}

interface C {

    void think();

}

class One implements A { ... }

class Two implements B { ... }

class Three implements B, C { ... }

任何使用多重继承的面向对象分析/设计(OOA/OOD)都可以轻松转换成Java代码。你提到需要不断改变“能力”这点有点让人担心:比如说,如果一辆Car可以move(),那它为什么会突然需要能够think()呢?

3

这要看你具体的使用场景,不过你有没有考虑过使用装饰器呢?

http://en.wikipedia.org/wiki/Decorator_pattern

撰写回答