Java - 如何选择要构造的子类

时间:2017-10-18 23:31:24

标签: java inheritance subclass extends

我有一个父类:

public class Animal {
  public Animal(String name, AnimalTypeEnum type) {
  }
}

我有很多(如果这导致我超过30岁)孩子:

public class Dog extends Animal {
  public Dog(String name, AnimalTypeEnum type) {
    super(name,type);
  }
}

public class Cat extends Animal {
  public Cat(String name, AnimalTypeEnum type) {
    super(name,type);
  }
}

对象是从项目中的许多不同位置构建的(在启动时加载,在运行时的不同时间创建。到"创建"对象,我目前使用此函数(在30以上的子类中)项目,而不仅仅是2):

public static Animal create(String name, AnimalTypeEnum type) {
  switch(type) {
    case DOG:
      return new Dog(name, type);
    case CAT:
      return new Cat(name, type);
  }
}

重要的是要注意,没有子类在参数上有任何差异。我使用子类的原因是因为它们有一个或两个被覆盖的函数。

说我现在想为所有子类添加一个参数,我需要:

  • 将参数添加到Animal构造函数
  • 将参数添加到子类构造函数
  • 将参数添加到create()功能
  • (也可以在调用create()函数的任何地方更改参数)

理想情况下,我希望消除更改子类参数(没有子类具有不同的参数)和上述过程中的create()函数。但如果这是不可能的,我想找到一个更好的create()功能替代品。我所想到的最佳解决方案(伪代码)是:

public Animal(String name, AnimalTypeEnum type) {
  if (type == CAT) this.subclass(Cat);
  if (type == DOG) this.subclass(Dog);
}

我认为上述内容违背了类继承的原则,所以我想清楚这不是我想要找到的解决方案,我想象一下可以工作的解决方案

这是一个相当微不足道的问题,但我觉得糟糕的编程习惯是背后的,我想纠正这些问题。我的问题是(因为我没有正确解释我的问题/原因):

  • 继承甚至是理想的做法吗?
  • 在这种情况下是否可以消除更改子类中构造函数的过程?
  • 我有什么办法可以删除create()函数,并在构建Animal时指定子类吗?

谢谢。

3 个答案:

答案 0 :(得分:0)

由于你有枚举来识别实例类型,你可以使用多态枚举来避免使用create / switch / if-else方法:

public enum AnimalTypeEnum {

    CAT {
        public Animal create(String name) {
            return new Cat(name);
        }
    },
    DOG {
        public Animal create(String name) {
            return new Dog(name);
        }
    },
    COW {
        public Animal create(String name) {
            return new Cow(name);
        }
    };

    abstract Animal create(String name);
}

因为这种方法的一切都有利有弊。请查看它是否符合您的要求。

答案 1 :(得分:0)

我认为你想使用工厂模式,所以你有任何解决问题的方法@Doleron展示了第一个,但你也可以使用它:

public interface Animal {
   public String getName();
}

实施狗

public class Dog implements  Animal{
   private String name;
   public Dog(String name) {
      this.name=name;
   }

   @Override
   public String getName() {
      return name;
   }

}

public class Cat implements Animal{
   private String name;
   public Cat(String name) {
       this.name=name;
   }

   @Override
   public String getName() {
       return name;
   }
}

public class AnimalFactory {
   /*
    * Some people use static attributs like:
    * public static final String DOG ="DOG";
    */
   public static Animal creatAnimal(String animal, String name){
     if("DOG".equalsIgnoreCase(animal)){
        return new Dog(name);

     } else if("CAT".equalsIgnoreCase(animal)){
        return new Cat(name);

     }
     return null;
   }     
}

主要

public static void main(String[] args) {
    Animal animal = AnimalFactory.creatAnimal("dog", "pluto");
    /*
     * if you use static attribut you can call this form
     */
    //Animal dog = AnimalFactory.creatAnimal(AnimalFactory.DOG, "pluto");
    System.out.println("Name "+animal.getName()+ " class "+animal.getClass().getSimpleName() );

    animal = AnimalFactory.creatAnimal("cat", "garfield");

    System.out.println("Name "+animal.getName()+ " class "+animal.getClass().getSimpleName() );
}

您可以看到另一个示例here

答案 2 :(得分:0)

首先,基类Animal应该是一个抽象类,因为你永远不会赋予Animal对象生命,而是赋予更具体的动物类型,即Dog,Cat等等。这样,所有动物都会有一些基本方法已经实现。但是,如果某些子类需要从另一个类继承,你应该将Animal视为一个接口,因为Java不允许多重继承。
对于您的第二个问题,如果我正确理解,为什么不能将受保护的成员添加到基类Animal并在Animal costructor中初始化它?最终,如果子类作为此参数的特定值,则可以在子类costructors中设置它 最后,对于我认为的create()函数,你应该考虑抽象工厂模式。