Python中的多重继承;如何在Java中实现?
我正在把一些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
这要看你具体的使用场景,不过你有没有考虑过使用装饰器呢?