如何在Java中组合两个对象?

时间:2013-11-27 14:38:59

标签: java design-patterns

考虑:

public class test01{

    public void doSomething(){
        // do something
    }

}

public class test02{

    public void printSomething(){
        // print something
    }

} 

// in main
test01 t1 = new test01();
test02 t2 = new test02();

// I want do to something like this
test01 t3 = t1.merge(t2);

// with t3 I should be able to access both t1 and t2 functions
t3.doSomething();
t3.printSomething();

如果可以在Java中使用,请告诉我?如果是,请告诉我如何实现这一目标?

7 个答案:

答案 0 :(得分:6)

java中没有多重继承。您可以做的是让test02成为test01的子类,然后创建test03作为test02的子类。

你可以将它们组成一个Test03类,如下所示:

public class Test03 {

    private Test01 test01;
    private Test02 test02;

    public void doSomething() {
        test01.doSomething();
    }

    public void printSomething() {
        test02.printSomething();
    }

}

请注意在java中,您不应该使用test01等类名。它们应该有意义并符合java类命名准则。

答案 1 :(得分:3)

你最好的选择可能就是:

public class TestSet {
    private test01 t1 = new test01();
    private test02 t2 = new test02();

    public void doSomething() {
        t1.doSomething();
    }

    public void printSomething() {
        t2.printSomething();
    }
}

在某些语言中,支持多重继承,这可能是您在这里寻找的。但不是用Java。您可能希望也可能不想在这里建立几个接口,以便将TestSet与test01和test02更紧密地结合在一起。

答案 2 :(得分:2)

  

如果可以在Java中使用,请告诉我吗?

这是不可能的。您不能像Java中那样动态地组合行为。

在Java中组合行为的常规方法是使用继承和包装或委派的某种组合。即使这样,也会出现子类型问题......除非你使用接口......因为Java不允许类有多个(直接)超类。

考虑@ Panzercrisis的例子。虽然他的test03类实现的方法与test01test02类具有相同的签名,但test03的实例与其中任何一个都不兼容。 (您不能将test03实例用作test01test02。Java不支持鸭子输入!)

要解决这个问题,您需要分别定义由face01face02实现的接口test01test02。然后,您将实施test03作为实施 {/ 1>}和face01

但这是所有静态类和静态类型。


在某些情况下,您可以使用face02或类似的东西来“合成”一个“合并”两个现有类行为的类。但是,这些都是在幕后使用静态类型和代码生成完成的。此外,这种方法只有在您有远见来定义一堆接口(例如DynamicProxyface01)并针对接口而不是实现类编写应用程序代码时才可行。

答案 3 :(得分:0)

你可以在另一个类X中将类Y定义为内部类,并且可以在类X中使用类Y.除此之外,我知道没有办法做到这一点。

答案 4 :(得分:0)

简短的回答,不,你怎么描述不可能。

如果test01test02接口和第三个类test03同时实现这两者,则可能会出现这种情况。在C ++中,这可以通过多重继承完成,但是它的功能大致相同(即你必须创建第三个类而不是扩展它们),而且这个选项在Java中都不可用。

另一种选择是某种组合,例如@Panzercrisis描述。

最后一个选项(我能想到)是test02延长test01但会改变test02

但一般来说,不,不可能。

答案 5 :(得分:0)

不,你不能,真正按照你描述的方式这样做, 你可以做到

  

公共类test01扩展test02 {....

     

}

所以你的test1,你可以使用这两个类的方法, 但是,如果你真的想要把课程合并在一起,你可以像这样憎恶:

public class MyObject {
    Map<String, Object> objects = new HashMap<String, Object>();
    Map<String, Method> methods = new HashMap<String, Method>();

    public Object execute(String methodAName)
{

    Object object = objects.get(methodAName);
    Method method = methods.get(methodAName);
    if (object==null || method==null)
    {
        throw new RuntimeException("method not found");
    }

    try {
        return method.invoke(object, null);
    } catch (Exception e) {
        throw new RuntimeException(e);

    }
}

    public void merge(Object o) {
        for (Method m : o.getClass().getMethods()) {
            objects.put(m.getName(), o);
            methods.put(m.getName(), m);
        }
    }
}

当你可以像那样使用它时

 MyObject o = new MyObject();
 o.merge(new test01());
 o.merge(new test02());

 o.execute("printSomething");
 o.execute("doSomething");

但正如我所说,不推荐

答案 6 :(得分:0)

你可以使用Java inheritance做类似的事情,但不是一回事。你可以在这里使用extends。但是你必须确保方法覆盖不会发生,否则你的要求不匹配。

Test02 extends Test01

然后

Test03 extends Test02 

现在你可以实现类似的东西了。

Test03 test=new Test03();

test.callMethodInTest1();
test.callMethodInTest2(); 

样品:

public class Test1 {

public String callMethodInTest1() {
    return "test1";
  }
}

public class Test2 extends Test1{

public String callMethodInTest2() {
    return "test2";
  }
}

public class Test03 extends Test2 {

public static void main(String[] args){
   Test03 sample=new Test03();
   sample.callMethodInTest1();
   sample.callMethodInTest2();
 }

}