首先对这个问题道歉 - 我是Java的新手,并且想不出用它来表达的好方法。
我有一个名为" Animal"的抽象类。还有一些叫做" Pig"," Horse"继承自" Animal"。
的等等我正在使用ArrayList来创建一个动物列表,这些动物是实例化的Pigs,Horses等。然后我想将动物从列表中拉出来并使用它们,但是Java只允许我与它们进行交互,如果它们是基类,Animal。
以下是我的主要代码的快速列表,应该更清楚:
import java.util.ArrayList;
public class Main {
public static void main(String[] args) {
ArrayList<Animal> animals = new ArrayList<Animal>();
animals.add(new Pig("Porkey", "pink"));
Animal animal = animals.get(0);
animal.introAnimal(animal);
animal.oink(); // Won't compile.Specific Pig class method
}
}
现在我知道我可以使用&#34; Pig animal = (Pig) animals.get(0)
&#34;但我的观点是,我希望能够与这些动物一起工作而不管它们是什么,如果我需要知道的话,可以使用getObjectType或稍后使用它。
看起来好像这是多态性的障碍:)我不太担心这个特定的代码(我只是在练习),但更多的是在这个问题的一般解决方案中。
非常感谢。
答案 0 :(得分:5)
您必须使用动物通用的术语。而不是指示动物oink
不适用于所有动物,你可以指示speak
这可能是一个通用术语。
Java是一种静态类型语言,因此如果您尝试使用可能在运行时无效的方法,编译器会抱怨。它不是一种动态语言,它允许您调用任何方法,希望它可以在运行时工作。虽然这更灵活,但是可靠地构建大型程序更加困难。例如说我重命名一个方法,我怎么知道谁调用该方法也重命名它。
abstract class Animal {
void speak();
}
class Pig extends Animal {
public void speak() {
System.out.println("Oink");
}
}
class Dog extends Animal {
public void speak() {
System.out.println("Woof");
}
}
class Duck extends Animal {
public void speak() {
System.out.println("Qwack");
}
}
List<Animal> animals = Arrays.<Animal>asList(new Dog(), new Pig(), new Duck);
for (Animal animal : animals)
animal.speak();
打印
Woof
Oink
Qwack
感谢您的回答。我试图得到的是,我希望能够创建一个列表,然后从列表中删除东西,并能够处理子类,具体取决于它在运行时的子类。我只是没有意识到你可以稍后再去获取子类方法。
有两种方法可以做到这一点。
List<Animal> animals = ...
for (Animal animal: animals)
if (animal instanceof Pig) {
((Pig) animal).oink();
}
这仍然要求你知道你想养猪。假设你有另一个班级Boar
并且它也有一个oink
方法,而你并不关心Pig和Boar没有父类(尽管你可以)
List<Animal> animals = ...
for (Animal animal: animals) {
Method method = animal.getClass().getMethod("oink");
if (method != null)
method.invoke(animal);
}
现在让我们说这个方法不仅不在Animal
中,而且对于猪来说它是private
,这使得它更难调用。
List<Animal> animals = ...
for (Animal animal: animals) {
Method method = animal.getClass().getDeclaredMethod("oink");
if (method != null) {
method.setAccessible(true);
method.invoke(animal);
}
}
答案 1 :(得分:4)
您可以使用instanceof
运算符(instanceof关键字可用于测试对象是否为指定类型。)以检查animal
是否引用Pig
以及是否 ArrayList<Animal> animals = new ArrayList<Animal>();
animals.add(new Pig("Porkey", "pink"));
Animal animal = animals.get(0);
animal.introAnimal(animal);
if (animal instanceof Pig)
((Pig)animal).oink(); // This will compile and work
,然后执行演员并调用Pig的特定方法。 E.g。
{{1}}
答案 2 :(得分:1)
如果超类包含一个方法execute()
,并且你在每个子类型中实现了这个函数,那么将执行正确的方法。
示例:
class pig extends Animal {
...
public void execute () {
System.out.println("Oink");
}
public void specificPigAction {
...
}
}
class cat extends Animal {
...
public void execute () {
System.out.println("Meow");
}
}
现在你可以这样做:
Animal pig = animals.get();
pig.execute(); // output = oink
Animal cat = animals.get();
cat.execute(); // output = meow
如果您希望执行非常具体的任务,可能只有猫,您必须将对象强制转换为正确的类型:
Pig pig = (Pig) animals.get();
pig.specificPigAction();
在后一种情况下,只有在知道类型正确或将其包含在throw catch子句中时,才能进行强制转换。
请注意,此代码可能不符合样式规则甚至Java语法,但我相信这个想法很明确。