是否可以扩展Class的实例

时间:2017-03-06 12:07:18

标签: java oop

例如,我有动物类,以及扩展动物类的Cat(Bird,Dog,Fish ......)。现在我想声明类Pet,它也是Animal,我希望它可以从任何现有的Animal构建,例如猫。

所以我需要像这样的构造函数:

class Pet extends Animal{
    private String nickname;
    private Animal kind;

    Pet(Animal a, String nickname){
        <...>;
        this.nickname = nickname;
    }
}

编辑: 我想要这样的东西:

Cat cat = new Cat();
Animal pet = new Pet(cat, "Foo");
if (pet instanceof Pet){
    if (pet.kind instanceof Cat){
         Pet.sayMeow();
    }
}

这是否意味着我只需要&lt; ...&gt;中的Animal()(受保护的)构造函数?

2 个答案:

答案 0 :(得分:1)

即使在您进行编辑之后,您的意图对我来说也不是很清楚。看起来好像你只是想找到一种方法,让你在运行时说:&#34;这只猫以前是流浪的,但它现在只是变成了某人的宠物!&#34 ;

如果那是对的,你可以选择一个非常简单直接的解决方案 - 将此功能添加到Animal类:

public class Animal {

  private boolean isPet = false;
  private String nickname = "";

  public Animal() {
    /*...*/
  }

  public makeStray() {
    isPet = false;
    nickname = "";
  }

  public makePet(String nickname) {
    isPet = true;
    this.nickname = nickname;
  }

  public boolean isPet() {
    return isPet;
  }

  public void makeNoise() {
    /* Override in child classes */
  }

}

根据你的例子,你可以简单地做:

Animal cat = new Cat();
cat.makePet("Foo");
if (cat.isPet()) { // Apparently, only pet cats ever meow.
     cat.makeNoise(); // Cats will meow, dogs will bark, ...
}

但请注意,这种编码方式可能会很快膨胀。这实际上取决于你计划用它做什么而不是这个。我说这是 quick&#39; n&#39;脏解决方案。

有关更复杂的解决方案,请查看其他答案。

EDIT1 :正如Fildor正确指出的那样,使用方法sayMeow()并不是一个好主意。最好在makeNoise()中使用Animal方法并在子类中覆盖它以获取不同种类动物的特定行为。现在,如果您从未想要实际创建Animal类的实例,您还可以创建类abstract以及makeNoise()方法。这将确保每个子类都必须实现makeNoise()方法。或者,如果方法没有被覆盖,你可以使用静音动物的默认行为。

EDIT2 This answer对相关问题可能会更清楚地了解您的情况。它是关于C#的,但原则转化为Java。

答案 1 :(得分:0)

您描述的内容完全可能,通常称为“装饰模式”。

仅链接答案很糟糕,稍后我会详细说明我有更多时间。

与此同时,维基百科有更多信息:Decorator Pattern

1 Cat cat = new Cat();
2 Animal pet = new Pet(cat, "Foo");
3 if (pet instanceof Pet){
4    if (pet.kind instanceof Cat){
5         Pet.sayMeow();
6    }
7 }

这样做的缺点是你需要使用instanceOf。通常,您的Animal课程会有一个方法 - 让我们称之为makeNoise。可能是抽象的。你动物实现(CatDog ...)然后将覆盖该方法以产生各自的噪音(“Bark”,“Miow”......)。

在片段中,似乎只有宠物可以发出声音......这会使它变得有点复杂,因为会有各种方法来做到这一点。

您可以让装饰者保存声音并覆盖makeNoise以发出声音。像这样:

Cat catInstance = new Cat();
catInstance.makeNoise(); // Default impl: NOP => "" - no sound.
Animal pet = new Pet( catInstance, "Mieow" );
pet.makeNoise(); // => "Mieow"

所有这一切的要点是:您希望避免使用instanceof。你不在乎动物是猫,宠物猫还是宠物狗。如果被告知,他们应该发出正确的声音。所以你可以拥有一个“动物”的集合,并告诉他们所有人“makeNoise”,每个人都会保持沉默,吠叫或mieow,如果他们是宠物或Animal的特定孩子,你不必照顾。 / p>

编辑:再次阅读我的答案,它更像是一个政策(策略模式),而不是一个装饰器。 该政策改变了某些事情的完成方式,而装饰者则会添加该功能。

因此,要成为一名真正的装饰者,这意味着makeNoise将位于Pet的界面中。这意味着你无法在动物身上调用该方法。

这就是为什么我将我的建议从“装饰者”改为“Strategy”模式。

上面的例子仍然存在。您可以采用“默认”策略,并使用类似Decorator的实现方法注入“Pet”-Strategy。

当然,所有这些也可以采用不同的方式来更严格地实施模式。

最后,if( x instanceof X) ...总是叮嘱“访客” - 贝尔。