java-从列表中调用子类

标签 java inheritance

我有这个代码:

public abstract class animal {
public final static int elephent = 1;
public final static int dog = 2;

和两个子类:

public class elephant extends animal {

    public final static int type = animal.elephent;

    public elephant (String name){
        super(name);
    }

}

public class dog extends animal {

    public final static int type = animal.dog;

    public dog (String name){
        super(name);
    }

}

现在,假设我有一个字符列表,其中包含字母 E-elephant 和 D-dog。 和相同大小的动物类的空列表。 对于第一个列表中的每个字符,我想创建一个正确动物的新实例。 示例:[“d”,“e”,“d”] 会给我一个列表:[新狗,新大象,新狗] 希望我说清楚了, 预先感谢您的帮助。

最佳答案

这个设计并不是最优的。您用整数变量指示类型,这确实不是一个好主意。

第一个改进:将类型指示设为枚举。

public enum AnimalType {
    ELEPHANT, DOG
}

现在在您的动物类中添加一个类型字段:

public abstract class Animal {
    private final AnimalType type;
    private final String name;
    protected Animal(AnimalType type, String name) {
        this.type = Objects.requireNonNull(type);
        this.name = Objects.requireNonNull(name);
    }
    // more fields and methods here
}

大象看起来像这样(狗也类似):

public class Elephant extends Animal {
    public Elephant(String name) {
        super(AnimalType.ELEPHANT, name);
    }
    // more fields and methods here
}

主要缺点:每次添加新的动物类型时,都必须添加新类向枚举添加类型。这不是最好的设计。此外,类型枚举并不是真正需要的,因为子类型已经保存了类型信息

Elephant 类的实例是大象(狗也是如此)。它不需要类型字段。

第二个改进:完全删除类型指示。没有整数,没有枚举。只要有抽象类和子类即可。

现在你的问题是,如何从任何字符输入中获取正确的实例。这称为映射。您想要 map

the character 'E' to the class Elephant.

the character 'D' to the class Dog.

这可以通过 Java Map 来实现:

Map<Character, Class<? extends Animal>> charToAnimal = new HashMap<>();
charToAnimal.put('E', Elephant.class);
charToAnimal.put('D', Dog.class);

Class<? extends Animal> animalClass = charToAnimal.get('E');
String name = ...;
Animal animal = animalClass.getConstructor(String.class).newInstance(name); // will be an Elephant instance

应该在您需要该行为的任何类中维护​​此映射,或者如果您刚刚学习如何做到这一点,则可以在 main 方法中维护此映射。

请注意,我使用了一种称为反射的 Java 机制,只是为了创建一个实例,因为没有其他通用方法来处理实例化。

另一种方法是执行相同操作的方法:

public Animal createAnimal(char c, String name) {
    if (c == 'E') {
        return new Elephant(name);
    } else if (c == 'D') {
        return new Dog(name);
    } else {
        throw new IllegalArgumentException(c);
    }
}

无论哪种方式,您不仅必须添加一个新的动物子类,而且还必须向映射添加一个条目(见上文)或向该方法添加一个 if 分支。

<小时/>

编辑,当我再次思考这个场景时。

您可以采用枚举方法并将类实例化放入此枚举中。采用上述动物类别和以下类型枚举(未选中):

public enum AnimalType {
    ELEPHANT('E', Elephant.class),
    DOG('D', Dog.class);
    
    private static final Map<Character, Class<? extends Animal>> CHAR_TO_ANIMAL = new HashMap<>();
    AnimalType(char c, Class<? extends Animal> animalClass) {
        CHAR_TO_ANIMAL.put(c, animalClass)
    }
    public Animal createAnimal(char c, String name) {
        if (c == 'E') {
            return new Elephant(name);
        } else if (c == 'D') {
            return new Dog(name);
        } else {
            throw new IllegalArgumentException(c);
        }
    }
}

关于java-从列表中调用子类,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22728702/

相关文章:

java - 如何从 HttpServletRequest 对象访问 Struts 值堆栈?

java - 在服务器上运行 Shell 脚本

java - 请解释最终的 AtomicReference

c++ - 声明指向基类和派生类的指针

c++ - 在 C++ 中查找内存中某个类的对象布局的算法

java - Spring数据分页和排序存储库,具有多个字段和日期

java - 使用带有 Eclipse IDE 的 Google map API 在 Java 中连接被拒绝错误,而相同的 URL 在浏览器中给我结果

c++ - 在 C++ 中为抽象类模板创建接口(interface)

java - 在这个例子中如何解决代码重复,我引入继承来实际解决代码重复

Python 使用方法链保留子类