繁体   English   中英

java-从列表中调用子类

[英]java- calling sub-class from a list

我有以下代码:

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-大象和D-狗的字符列表。 以及相同大小的动物类别的空列表。 对于第一个列表上的每个字符,我想创建一个正确的动物的新实例。 例如:[“ 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类的一个实例是大象(狗相同)。 它不需要类型字段。

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

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

Elephant类的字符“ E”。

Dog类的字符“ D”。

这可以通过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);
    }
}

无论哪种方式,您都不仅需要添加一个ne动物子类,而且还必须在地图中添加一个条目(请参见上文)或该方法的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);
        }
    }
}

因此,您可能要考虑的事情之一是switch-case语句。 因此,在Java中,您可以执行以下操作:

// get a char from the list.
char animal;

switch(animal)
{
    case'e':
        Elephant varName = new Elephant("Dumbo");
        newList.add(varName);
        break;
}

我没有在此处包括所有内容,但这应该可以帮助您入门。 您将需要通过数据结构查找迭代(循环)。

老实说,自从我编写任何Java以来​​已经有一段时间了,但这是您可以执行此操作的一种方式。 还有其他方法也可以执行此操作,例如也可以使用if块。

希望这可以帮助。

我认为你需要的是一个静态工厂方法返回一个实例,这是一种方法。

抽象类:

public abstract class animal {
public final static char elephent = 'E';
public final static char dog = 'D';
}

大象班:

public class Elephant extends Animal {

    private char myType;
    private String name;

    public Elephant(char type, String name) {
        super();
        this.myType = type;
        this.name = name;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public char getMyType() {
        return myType;
    }

    public void setMyType(char myType) {
        this.myType = myType;
    }

}

狗类:

public class Dog extends Animal {

    private char myType;
    private String name;

    public Dog(char type, String name) {
        super();
        this.myType = type;
        this.name = name;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public char getMyType() {
        return myType;
    }

    public void setMyType(char myType) {
        this.myType = myType;
    }

}

工厂类别:

public class FactoryMethod {

    static char getAnimalIndex(char type){

        switch (type) {
        case 'E':
        case 'e':
            return Animal.ELEPHANT;
        case 'D':
        case 'd':
            return Animal.DOG;
        default:
            throw new IllegalArgumentException(String.valueOf(type));
        }
    }

    public static Animal getInstance(char type, String name){
        Animal myCategory = null;
        switch (getAnimalIndex(type)) {
        case Animal.ELEPHANT:
            myCategory = new Elephant(type,name);
            break;
        case Animal.DOG:
            myCategory = new Dog(type,name);
            break;
        }
        return myCategory;
    }

}

用法:

如果您需要使用动物类索引,或者将其与列表中的字符一起使用,则此工厂方法有效。 获取实例:

//using Animal index
FactoryMethod.getInstance(Animal.ELEPHANT,"Elephant");
FactoryMethod.getInstance(Animal.DOG,"Dog");

//using characters in list
FactoryMethod.getInstance('character_in_list_here',"Name OF The Animal Here");

由于它是静态方法,因此您无需使用FactoryMethod实例即可使用。 我希望这就是你所需要的。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM