Python中的多重继承;在Java中如何做到这一点?

发布于 2024-10-10 03:54:59 字数 262 浏览 0 评论 0原文

我正在将一些 Python 代码移植到 Java,但在处理以下问题时遇到了麻烦:

我有一些类需要具备能力 A、B 或 C。类 1 需要能力 A,类 2 需要能力 A、B 和C,而3级需要B和C。最重要的是,我希望能够轻松地改变将来什么职业可以拥有什么能力。

我通过 Python 中的多重继承很容易地解决了这个问题。我正在尝试找出用 Java 实现这一点的最佳方法,但我无法想出一个好的解决方案。我知道多重继承是不受欢迎的,所以我很高兴能学到更好的方法。

谢谢!

I'm porting some Python code to Java, and I am having trouble dealing with the following problem:

I have some classes which need to have abilities A, B, or C. Class 1 needs ability A, class 2 needs A, B and C, and class 3 needs B and C. Most importantly, I want to easily be able to change what class can have what ability in the future.

I solved this problem pretty easily with multiple inheritance in Python. I'm trying to figure out the best way to do it in Java, but I can't come up with as good of a solution. I know multiple inheritance is frowned-upon, so I'd appreciate being taught a better way.

Thanks!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(8

云淡月浅 2024-10-17 03:54:59

这取决于您的实际用例,但是您已经考虑过装饰器了吗?

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

It depends on your actual use case, but have you already considered decorators?

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

彩扇题诗 2024-10-17 03:54:59

多重继承并不令人反感。令人皱眉的是“实现继承”(也称为“代码重用”),因为它会导致无法解决的“钻石问题”。因为代码重用实际上与面向对象没有太大关系。

您想要做的事情可以使用多重继承来解决(如果您需要进行“代码重用”,则可以使用委托)。

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。你说你需要一直改变“能力”的部分有点可怕:如果,比如说,一辆汽车可以move(),为什么它会突然需要能够think()

Multiple-inheritance ain't frowned upon. What is frowned upon is "implementation inheritance" (also known as "code reuse"), because it leads to the unsolvable "diamond problem". And because, well, code-reuse really hasn't much to do with OO.

What you want to do can be solved using multiple inheritance (and, say, delegation if you need to do "code reuse").

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 { ... }

Any OOA/OOD using multiple inheritance can be trivially translated to Java. The part where you say that you need to change the "ability" all the time is a bit scary: if, say, a Car can move(), why would it suddenly need to be able to think()?

江城子 2024-10-17 03:54:59

您可以相当轻松地使用 AspectJ 的 mixin 语法来模拟多重继承(也可以在编译时模拟)。首先,为您想要混合的功能声明一个接口:

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();
    }
}

您需要使用方面j 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");

You can use AspectJ's mixin syntax fairly easily to emulate multiple inheritance (and at compile time too). First, declare an interface for the functionality you want to mixin:

public interface A{
    String getSomethingForA();
}

then define an annotation which you can use to signify that you want the mixin applied to a given class:

public @interface WithA {}

then add the annotation to the class you want to use:

@WithA
public class MyClass {}

then, to actually add some functionality:

@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();
    }
}

You'll need to use the aspectj jars and run the aspects as part of your compile process, but this lets you create truly modularized functionality and then forcibly merge it into your classes later. To access your class with the new functionality, do the following:

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

You can apply the same annotation to another class and cast it as well:

@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");
妥活 2024-10-17 03:54:59

多重继承几乎总是一个坏主意,因为它的效果通常可以通过其他机制来实现。根据您对问题的描述,听起来您想

  1. 使用接口来定义行为(公共接口 A),在这种情况下,每个行为可能应该有自己的接口。

如果 2 个行为紧密耦合(例如 A 和 B),则定义一个实现这两个原子接口的接口(公共接口 CombinedAandB 扩展 A、B)

  1. 定义一个实现该接口的抽象基类,为行为提供默认实现

    公共抽象类BaseAB实现A、B
    {
       @覆盖 
       公共无效A(){添加(0,1); }
    
    
    <预><代码> @Override
       公共无效B(){添加(1,0); }
    
    
       private void add(int a, int b) //它不返回。没有汤给你。
       { a + b; //如果你知道为什么这是错误的,请自己高五。 }
    

    }

  2. 定义一个扩展抽象基类的具体类,实现另一个接口,并提供自己的行为。

    公共类 IDoABAndC 扩展 BaseAB 实现 C
    {
    //东西等等
    }

Multiple inheritance is almost always a bad idea, as its effects can usually be achieved through other mechanisms. Based upon your description of the problem, it sounds like you want to

  1. Use interfaces to define behavior (public interface A) in this scenario, each behavior should probably have its own interface.

If 2 behaviors are tightly coupled (say A & B), define an interface that implements those two atomic interfaces (public interface CombinedAandB extends A, B)

  1. Define an abstract base class that implements the interface to provide default implementations for behaviors

    public abstract class BaseAB implements A, B
    {
       @Override 
       public void A() { add(0,1); }
    
    
    
       @Override
       public void B() {add(1,0); }
    
    
       private void add(int a, int b) //it doesn't return. no soup for you.
       { a + b; //If you know why this is wrong, high five yourself. }
    

    }

  2. Define a concrete class that extends the abstract base class, implements another interface, and provides its own behavior.

    public class IDoABAndC extends BaseAB implements C
    {
    //stuff, etc
    }

空袭的梦i 2024-10-17 03:54:59

您可以在接口中定义功能并在类中实现它们。

You can define the abilities in interfaces and implement them in your classes.

小瓶盖 2024-10-17 03:54:59

在java中你没有多重继承,而是可以实现多个接口。

因此,类 1 将实现接口 A 和 B。类 2 将实现接口 A、B 和 C。类 3 将实现接口 B 和 C。

In java you don't have multiple inheritance, instead you can implement multiple interfaces.

So your class 1 will implement interface A and B. Class 2 will implement interface A, B and C. Class 3 will implement B and C.

日裸衫吸 2024-10-17 03:54:59

如果您需要的是接口继承,那么正如前面提到的,您始终可以实现多个接口。

如果您正在寻找实现继承,那么您有点运气不好。最好的解决方案可能是使用委托——用字段替换额外的超类,并实现仅委托给这些字段的方法。它确实需要编写大量重复的委托方法,但这在 Java 中是不可避免的(无需求助于 AspectJ 或其他字节码处理技巧;小心,这种方式很疯狂……)。

If what you need is interface inheritance, then as mentioned before, you can always implement multiple interfaces.

If you're looking for implementation inheritance, you're somewhat out of luck. The best solution is probably to use delegation — replace the extra superclasses with fields, and implement methods that just delegate to those fields. It does require writing a lot of repetitive delegation methods, but it's rather unavoidable in Java (without resorting to AspectJ or other bytecode-munging tricks; careful, this way madness lies …).

挽清梦 2024-10-17 03:54:59

这有点离题,但您可以通过 Jython (http://www.jython.org/) 在 Java 中运行 Python 代码。这解决了向 Java 部分的移植,而不是解决多重继承部分(我认为您需要确定哪个是相关的)

This is a bit tangential, but you can have python code running in Java via Jython (http://www.jython.org/). This addresses the porting to Java part, not the solving multiple inheritance part (I think you need to determine which is relevant)

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文