1

假设我有一个存储泛型类型的集合,例如

public class MyCollection<T> {
    public T getNext()
    {
        //Remove T from list
        //Return T
    }
}

我正在使用这个集合来存储子类型,例如

public class NormalPerson extends Human {
    public void beNice() { }
}
public class Murderer extends Human {
    public void kill() { }
}

...

MyCollection<Human> people = new MyCollection<>();

people.add(new NormalPerson());
people.add(new Murderer());

我想调用特定于每个子类型的方法。例如

Human person = people.getNext();
switch(person.getType()) {
    case NORMAL:
        person.beNice(); //Symbol not found
        break;
    case MURDERER:
        person.kill(); //Symbol not found
        break;
}

但是我不能,除非我投,例如

switch(people.getNext().getType()) {
    case NORMAL:
        NormalPerson person = (NormalPerson)people.getNext();
        person.beNice();
        break;

铸造是完成这项工作的唯一方法吗?我会以错误的方式解决这个问题吗?

谢谢

4

3 回答 3

1

如果您希望 Human 能够执行这两种操作,则需要在 Human 中声明这一点。

一个更简单的方法是有一个通用的act方法,它可以让一个人变得友善,让一个人杀人。这样调用者就不需要知道人类将采取什么行动。

于 2013-06-01T11:29:51.877 回答
0

你正在以错误的方式去做。调用代码不应该检查甚至关心对象的确切类型,知道它是某种Human.

解决这个问题的一种常见方法是为方法取一个更通用的名称,maybe Human#doAction(),并让每个扩展类Human通过覆盖该方法来定义其特殊行为。这样,无论您拥有哪种方法,Human您都可以调用相同的方法,这大大简化了您的代码。

于 2013-06-01T11:28:33.490 回答
0

编译器只能理解引用类型。因此,当您编写 Human 时,编译器将尝试在 Human 类中查找它无法找到的方法,因为它实际上是实现 Human 的其他东西,而试图调用的方法不在 Human 中本身。

您可以做的是您可以使用 instanceof 运算符来检查它实际上是什么类型的对象,否则强制转换是唯一的方法。

例如

Human h=new Killer();

if(h instanceof Killer)
{
    (Killer)h.kill();
}

希望这可以帮助。

于 2013-06-01T11:29:06.753 回答