Java - 我可以扩展一个类的实例,使其成为父类实例吗?

时间:2015-08-19 12:41:56

标签: java oop inheritance instance maintainability

这是我想要实现的一个小例子。我有一个包含许多参数的类 - Dog。我有一个子课JumpyDog,我想学习如何“扩展”Dog的实例,使其成为JumpyDog的实例。

class Dog {
    int age, numberOfTeeth, grumpiness, manyOtherParameters;
    JumpyDog learnToJump(int height) {
        JumpyDog jumpy = new JumpyDog(this); // I do not want to copy all parameters
        jumpy.jumpHeight=height;
        return jumpy;
    }
}

class JumpyDog extends Dog {
    int jumpHeight;
    void jump(){}
}

或者我可以这样说:

Dog dog=new Dog();
dog.makeJumpy();
dog.jump()

5 个答案:

答案 0 :(得分:2)

您可以在Java中实现Decorator pattern,以避免在"扩展程序期间复制初始对象中的所有字段。通过内部保持对它的引用,但它不再是Dog(因为Dog类具有我们避免复制的字段。)

class JumpyDog {
    Dog meAsDog;
    int jumpHeight;

    public JumpyDog(Dog me) {
        meAsDog = me;
    }

    public Dog meAsDog() {
        return meAsDog();
    }

    void jump(){}
}

您可以像以下一样使用它:

Dog dog=new Dog();
JumpyDog meAsJumpy = dog.learnToJump(100);
meAsJumpy.jump()

不,您不能在示例中执行以下操作,因为Dog没有jump()方法:

Dog dog=new Dog();
dog.makeJumpy();
dog.jump() // Dog has no method jump

答案 1 :(得分:0)

你可以这样做:

class Dog {

    int age;
    int numberOfTeeth;
    int grumpiness;
    int manyOtherParameters;

    boolean hasLearnedHowToJump;
    int jumpHeight;

    void learnToJump(int heigth) {
        hasLearnedHowToJump = true;
        jumpHeight = heigth;
    }

    void jump(){
        if(!hasLearnedHowToJump) {
            throw new RuntimeException("must learn how to jump first...");
        }
    }

}

那么你就可以这样使用它:

Dog dog=new Dog();
//dog.jump() would end in a exception...
dog.learnToJump(100);
dog.jump()

答案 2 :(得分:0)

一旦dog被声明为Dog类型,这就永远是它的类型。您可以将其投射到任何超级班级,但它仍然是Dog

您可以使用复制构造函数。这实际上要求您为所有属性编写一些复制代码,但会为您提供接近您所需风格的内容。

public class Dog {

    int age, numberOfTeeth, grumpiness, manyOtherParameters;

    public Dog() {

    }

    public Dog(Dog other) {
        other.age = this.age;
        other.numberOfTeeth = this.numberOfTeeth;
        other.grumpiness = this.grumpiness;
        other.manyOtherParameters = this.manyOtherParameters;
    }
}


class JumpyDog extends Dog {

    int jumpHeight;
    void jump(){}

    public JumpyDog(Dog other) {
        super(other);
    }

}

会让你写下像:

Dog dog = new Dog();
JumpyDog jumpyDog = new JumpyDog(dog);
jumpyDog.jump();

离开你2个实例。这将使jumpyDog跳转,但不会对dog实例执行任何操作。

答案 3 :(得分:0)

你可以做这样的事情

class Dog {
    protected int age, numberOfTeeth, grumpiness, manyOtherParameters;

    protected Dog(Dog g) {
        // assign all attributes here
    }

    JumpyDog learnToJump(int heigth) {
        return new JumpyDog(this, heigth);;
    }


}

class JumpyDog extends Dog {

    int jumpHeight;

    public JumpyDog(Dog dog, int jumpHeight) {
        super(dog);
        this.jumpHeight = jumpHeight;
    }
    void jump(){}
}

然后你可以这样做:

Dog dog=new Dog();
JumpyDog jDog = dog.learnToJump(100);
jdog.jump()

答案 4 :(得分:0)

最好是实施链接论文所描述的Role Object Pattern。这是@Philip Voronov已经建议的类似装饰的图案。有一个概念作为接口,由一个核心和一个抽象类实现,该类表示一个对象可以播放的所有角色的超类。为了缓解object schizophrenia(在逻辑单元对象在许多物理对象之间分配时出现),每次对角色对象的调用(对角色来说都不是特定的)都会被转发到核心对象。

逻辑上,核心及其角色构建一个单元。但是对象被分成核心(管理角色)和对象可以扮演的所有角色。

客户端要么与核心对象交谈,要么与角色对象交谈。您可以在运行时添加和删除角色。

我用你的狗情景写了a short implementation

它提供了逻辑狗(世界已知的狗的概念)与其所有能力之间的分离。因此,您不必了解先验能力。