具有额外属性的子类构造函数

Subclass constructor with extra attributes

如果我有一个 class 'Dog' 扩展另一个 class 'Animal' 并且 Animal class 有一个构造函数,它有几个属性,比如 latinName, latinFamily等等 我应该如何为狗创建构造函数?我是否应该包括在 Animal 中找到的所有属性,以及我想要在 Dog 中找到的所有额外属性,如下所示:

public Animal(String latinName){
    this.latinName = latinName;
}

public Dog(String latinName, breed){
    super(latinName);
    this.breed = breed;
}

实际 classes 的属性比我在这里列出的要多得多,因此狗的构造函数变得相当长,让我怀疑这是要走的路还是有更简洁的方法?

如果 Dog extends Animal 那么是的,你会想继续使用 Animal 的参数(因为狗确实是一种动物)并且 可能 添加更多以区分狗和动物 objects。

所以一般来说,是的,您需要包括所有 parent classes 的参数。

还要考虑多个构造函数的参数列表可能更短的可能性。假设 Animal 有一个参数 String type,它定义了 child class 是什么类型的动物,你不需要每次都为 Dog 传递它。

public Dog (String name){
   super("Dog", name);
}

如果我对这一切有歧义,请告诉我,我会尽力澄清。

Should I include all attributes that are found in Animal...

那些对狗来说不是不变的,是的(一种或另一种方式;见下文)。但是例如,如果 AnimallatinFamily,那么你不需要 Dog 来拥有它,因为它总是 "Canidae"。例如:

public Animal(String latinFamily){
    this.latinFamily = latinFamily;
}

public Dog(String breed){
    super("Canidae");
    this.breed = breed;
}

如果您发现构造函数的参数数量不合适,您可以考虑构建器模式:

public class Dog {

    public Dog(String a, String b, String c) {
        super("Canidae");
        // ...
    }

    public static class Builder {
        private String a;
        private String b;
        private String c;

        public Builder() {
            this.a = null;
            this.b = null;
            this.c = null;
        }

        public Builder withA(String a) {
            this.a = a;
            return this;
        }

        public Builder withB(String b) {
            this.b = b;
            return this;
        }

        public Builder withC(String c) {
            this.c = c;
            return this;
        }

        public Dog build() {
            if (this.a == null || this.b == null || this.c == null) {
                throw new InvalidStateException();
            }

            return new Dog(this.a, this.b, this.c);
        }
    }
}

用法:

Dog dog = Dog.Builder()
            .withA("value for a")
            .withB("value for b")
            .withC("value for c")
            .build();

这使得更容易清楚哪个参数是哪个,而不是构造函数的一长串参数。你得到了清晰的好处(你知道 withA 指定了 "a" 信息,withB 指定了 "b",等等)但没有半建的危险Dog 实例(因为部分构造的实例是不好的做法); Dog.Builder存储信息,然后build进行构造Dog的工作。