从超级项目创建子对象

时间:2013-06-17 20:41:36

标签: java design-patterns inheritance

我有类Class1的object1。我想将类Class1扩展为Class2,添加一个方法,然后创建Class2的object2,它将在所有方法中完全作为object1运行,除了现在它将有一个额外的方法。

Class1 object1 = new Class1();
Class2 object2 = new Class2(object1);
object2.oldMethod();
object2.newMethod();

object1.oldMethod应该与object2.oldMethod具有完全相同的行为。一种愚蠢的方法是编写一个脚本来生成新类,其中包含来自Class1的100多个继承方法:

public class Class2 {
    private final Class1 object1;
    public Class2(Class1 object1) {
         this.object1 = object1;
    }

    public void oldMethod() {
        object1.oldMethod();
    }
    ...
    public void newMethod() {
    ...
    }
}

但我希望比那更聪明。怎么样?

修改: 我很抱歉没有说清楚。我从第三方获得了object1,这个对象带有一些内部状态 - 比如之前有一些setter在上面运行。我需要让object2具有相同的内部状态(这就是我在执行方法时的相同行为的意思)。我不能只扩展Class1,然后从Class2获取object2。 object2如何知道object1的状态?我不知道object1的内部状态(变量,数组,字段)。

EDIT2: 我想包装object1,但不想为保持相同的内容编写100个包装器方法。

5 个答案:

答案 0 :(得分:1)

public class Class2 extends Class1{
    //signature of old method, with the same parameters (if exists).
    public void oldMethod(){
        super.oldMethod(); //call the Class1 method
        //do what you have to do for this class down here.
    }
}

这种行为称为多态,在这种情况下,您将超类委托为通用的,只实现对您已经工作的类非常重要的内容。

答案 1 :(得分:1)

除非Object1具有复制构造函数,否则不能使用继承,因为您从API接收Object1的实例而不是自己构建它。

您可能想要的是Decorator Pattern。在这种模式中,装饰器由另一个对象组成,并通过装饰器向对象添加功能。

class Object1 {
    //...stuff...
}

class Decorator {
    private Object1 object;
    public Decorator(Object1 obj) {
        object = obj;
    }
    public Object1 getComposite() {
        return object;
    }
    public void extra() {
        //Do stuff with object1 and any other state specific to the decorator
    }
}

这也可以作为继承来完成,但只有在你真正尝试扩展Object1的接口而不是简单地增强接口时才有意义。

作为一个单独的说明,我认为实际尝试扩展第三方类是不明智的,除非文档明确表明该类是为扩展而设计的。未来的版本可能会将类标记为final,或者构建类可能很复杂或者具有包/私有访问权。此外,根据您的编辑,甚至可能无法实现。 Object1需要复制构造函数,以便您可以扩展它并从Object2构建Object1的实例。

答案 2 :(得分:0)

Class Class1{
    public void methodx(){

    }
}

class Class2 extends Class1{
    public void extraMethod(){

    }

}

继承是完美的案例。此处methodx将继承与class1class2中定义的完全相同的行为,您可以定义一个与class2相关的新行为。

答案 3 :(得分:0)

我认为你应该继承。详细说明zerocool的注释,可以声明Class2扩展Class1。

Class Class1{
    public void methodx(){

    }
}

class Class2 extends Class1{
    public void extraMethod(){

    }

}

然后你仍然可以拥有

Class1 obj = new Class2();

这将为您提供Class1参考的Class2 obj。

如果你真的想要一个从Class2到Class1的数据转换器,你可以写一个Class2的重载构造函数,它接受如下的Class1对象:

public Class2 (Class1 obj)
{
    this.setName(obj.getName()); //Assuming name attribute
    ... // and other setter methods
}

修改

作为包装器,您可以执行以下操作:

public class Class2
{
    private Class1 obj;

    public Class1 getClass1Obj()
    {
        return obj;
    }

    public void newMethod()
    {
        // your method here
    }
}

可以在getClass1Obj()返回的对象上调用旧方法,并直接在newMethod()的对象上调用Class2

答案 4 :(得分:0)

您可以使用AspectJ和ajc编译器尝试以下操作。

// Class1Extensions.aj
aspect Class1Extensions {
    // An inter-type declaration
    public void Class1.newMethod() {
       //...
    }
}

您需要使用ajc进行编译,以便调用object1.newMethod()的代码不会反叛。您还可以为newMethod创建一个界面并进入该方面:

declare parents Class1+ implements Class1NewMethods;

然后,你可以写

Class1NewMethods object2 = (Class1NewMethods) object1;
object2.newMethod();