如何调用列表中某些对象实现的特定接口? Java
How do I call specific interfaces that are implemented by some objects in a List? Java
假设我有一只基本动物class
abstract class Animal {
// basic animal code
}
现在我有 2 种不同的动物...
public class Dog extends Animal{
// dog code
}
和
public class Bird extends Animal implements Flyable{
// bird code
@Override
public void fly() {
System.out.println("flap flap");
}
}
Flyable 是一个包含单一方法的简单接口:
public void fly();
如果我有一个动物列表并且我想遍历它,告诉鸟儿飞但让狗独自一人,我该如何实现这个?
public class Test {
public static List<Animal> animals = new ArrayList<Animal>();
public static void main(String[] args) {
animals.add(new Bird("flop"));
animals.add(new Dog("plop"));
for(Fly f : animals) { // exception here because of mismatch of types
f.flap();
}
}
}
到目前为止我发现的唯一选择是使用 instanceof 来确定 class 是否实现了 Flyable 接口,但是快速 google 搜索表明这对业务不利。
来源例如:
https://www.quora.com/Is-using-instanceof-in-Java-consider-bad-practice-Any-alternative-to-using-this-keyword
将 instanceof 的使用视为糟糕的设计。
我觉得有一种我以前见过的直观方法可以做到这一点,但找不到好的解决方案。
Flyable is a simple interface that holds a single method:
public void fly();
我想这是一个打字错误,因为您调用的方法被命名为 flap
而不是 fly
.
您可以通过使用 instanceof
关键字检查 class is-a
superclass.
来解决问题
for(Animal animal : animals) { // loop through all animals
if(animal instanceof Flyable) { // if that animal IS-A Flyable (so it can fly)
((Flyable) animal).flap(); // cast to Flyable and let it fly!
}
}
The only option I have found so far is using instanceof to determine whether a class implements the Flyable interface, but a quick google search suggests this is bad for business
在我看来一点也不差。这是完成任务的唯一方法。
当您在 Animal
class 中实现包含 fly()
方法声明的 Flyable
接口时,您只需定义每个子 class 的动物有飞行能力。
在我看来,使用 instanceof
是一种不好的做法,因为它会使代码非常混乱:一方面 Dog 有一个 fly() 实现(它通过 Animal 间接实现 Flyable 接口class),另一方面,在接口实例上调用 fly() 时不会调用它。
你至少有 2 种方法可以防止 Dog
拥有飞行能力,这是我最喜欢的两种方法:
您可以创建 2 个 classes,FlyingAnimal
和 NonFlyingAnimal
,它们都扩展 Animal
class 而 FlyingAnimal
class 实现了 Flyable 接口而 NonFlyingAnimal
没有。
鸟将扩展 FlyingAnimal
class 而狗将扩展 NonFlyingAnimal
class。
通过这种方式,您可以创建一个 FlyingAnimal
列表,迭代它,并对它的每一个飞行成员调用 fly()
方法(狗不是其中之一)。
使用策略设计模式:
public interface Flyable {
String fly();
}
class ItFlys implements Flyable {
public String fly() {
return "I can fly";
}
}
class CantFly implements Flyable {
public String fly() {
return "I can't fly";
}
}
public class Animal {
private String name;
private double height;
private int weight;
private String favFood;
private double speed;
private String sound;
public Flyable flyingType;
public String tryToFly() {
return flyingType.fly();
}
public void setFlyingAbility(Flyable newFlyType) {
flyingType = newFlyType;
}
}
public class Bird extends Animal{
public Bird() {
super();
flyingType = new ItFlys();
}
}
public class Dog extends Animal{
public Dog() {
super();
flyingType = new CantFly();
}
}
这样,您就为Animal
的每个子class设置了飞行类型。
当您在 Dog
class 上调用 fly()
方法时,您将获得 "non-flying animal" 行为。
一种替代方法是组织您的对象,这样您就不必检查每个对象来确定如何处理它。例如,您可以维护一个 Kingdom
class 和 Animal
的各种集合,包括 Flyable
集合。迭代 Flyable 集合不需要测试每个实例是否是 Flyable。如果您有其他 classes 仅在 Flyable 对象上运行,它们也不必测试每个成员,从而导致代码更清晰,工作更少。
您可以使用以下几种可能性:
将fly()
作为抽象方法放在基class中。使 Dog
的实现抛出 CannotFlyException
,或者以其他方式实现某些 "non-flying" 行为。然后使用
遍历你的 List<Animal>
try {
animal.fly();
catch (CannotFlyException() cfe) {
System.out.println("grounded!");
}
为您的 Animal() class 提供一个列出支持的操作的抽象方法,然后测试每个成员以查看它是否实现了 fly() 方法:
public abstract class Animal {
private Set<String> behaviors;
public Animal() {
behaviors = new HashSet<String>();
}
public Set<String> getBehaviors() {
return behaviors;
}
}
public class Dog extends Animal {
public Dog() {
super();
behaviors.add("fetch");
}
public String fetch(String fetched) {
return "Dog fetched " + fetched;
}
}
public class Bird extends Animal implements Flyable {
public Dog() {
super();
behaviors.add("fly");
}
@Override
public String fly() {
return "flap flap";
}
}
....
List<Animal> animals = MagicalAnimalListCreator.MakeAnimalList();
for (Animal animal : animals) {
if (animal.getBehaviors().contains("fly")) {
animal.fly();
}
}
你可以按照你目前的方式来做,但是在尝试飞行之前尝试将你列表中的每个成员都投射到 Bird 并抓住 ClassCastException。如果施法成功,你就会得到一只鸟并且可以飞了。
假设我有一只基本动物class
abstract class Animal {
// basic animal code
}
现在我有 2 种不同的动物...
public class Dog extends Animal{
// dog code
}
和
public class Bird extends Animal implements Flyable{
// bird code
@Override
public void fly() {
System.out.println("flap flap");
}
}
Flyable 是一个包含单一方法的简单接口:
public void fly();
如果我有一个动物列表并且我想遍历它,告诉鸟儿飞但让狗独自一人,我该如何实现这个?
public class Test {
public static List<Animal> animals = new ArrayList<Animal>();
public static void main(String[] args) {
animals.add(new Bird("flop"));
animals.add(new Dog("plop"));
for(Fly f : animals) { // exception here because of mismatch of types
f.flap();
}
}
}
到目前为止我发现的唯一选择是使用 instanceof 来确定 class 是否实现了 Flyable 接口,但是快速 google 搜索表明这对业务不利。 来源例如: https://www.quora.com/Is-using-instanceof-in-Java-consider-bad-practice-Any-alternative-to-using-this-keyword 将 instanceof 的使用视为糟糕的设计。
我觉得有一种我以前见过的直观方法可以做到这一点,但找不到好的解决方案。
Flyable is a simple interface that holds a single method:
public void fly();
我想这是一个打字错误,因为您调用的方法被命名为 flap
而不是 fly
.
您可以通过使用 instanceof
关键字检查 class is-a
superclass.
for(Animal animal : animals) { // loop through all animals
if(animal instanceof Flyable) { // if that animal IS-A Flyable (so it can fly)
((Flyable) animal).flap(); // cast to Flyable and let it fly!
}
}
The only option I have found so far is using instanceof to determine whether a class implements the Flyable interface, but a quick google search suggests this is bad for business
在我看来一点也不差。这是完成任务的唯一方法。
当您在 Animal
class 中实现包含 fly()
方法声明的 Flyable
接口时,您只需定义每个子 class 的动物有飞行能力。
在我看来,使用 instanceof
是一种不好的做法,因为它会使代码非常混乱:一方面 Dog 有一个 fly() 实现(它通过 Animal 间接实现 Flyable 接口class),另一方面,在接口实例上调用 fly() 时不会调用它。
你至少有 2 种方法可以防止 Dog
拥有飞行能力,这是我最喜欢的两种方法:
您可以创建 2 个 classes,
FlyingAnimal
和NonFlyingAnimal
,它们都扩展Animal
class 而FlyingAnimal
class 实现了 Flyable 接口而NonFlyingAnimal
没有。 鸟将扩展FlyingAnimal
class 而狗将扩展NonFlyingAnimal
class。 通过这种方式,您可以创建一个FlyingAnimal
列表,迭代它,并对它的每一个飞行成员调用fly()
方法(狗不是其中之一)。使用策略设计模式:
public interface Flyable {
String fly();
}
class ItFlys implements Flyable {
public String fly() {
return "I can fly";
}
}
class CantFly implements Flyable {
public String fly() {
return "I can't fly";
}
}
public class Animal {
private String name;
private double height;
private int weight;
private String favFood;
private double speed;
private String sound;
public Flyable flyingType;
public String tryToFly() {
return flyingType.fly();
}
public void setFlyingAbility(Flyable newFlyType) {
flyingType = newFlyType;
}
}
public class Bird extends Animal{
public Bird() {
super();
flyingType = new ItFlys();
}
}
public class Dog extends Animal{
public Dog() {
super();
flyingType = new CantFly();
}
}
这样,您就为Animal
的每个子class设置了飞行类型。
当您在 Dog
class 上调用 fly()
方法时,您将获得 "non-flying animal" 行为。
一种替代方法是组织您的对象,这样您就不必检查每个对象来确定如何处理它。例如,您可以维护一个 Kingdom
class 和 Animal
的各种集合,包括 Flyable
集合。迭代 Flyable 集合不需要测试每个实例是否是 Flyable。如果您有其他 classes 仅在 Flyable 对象上运行,它们也不必测试每个成员,从而导致代码更清晰,工作更少。
您可以使用以下几种可能性:
将
遍历你的fly()
作为抽象方法放在基class中。使Dog
的实现抛出CannotFlyException
,或者以其他方式实现某些 "non-flying" 行为。然后使用List<Animal>
try { animal.fly(); catch (CannotFlyException() cfe) { System.out.println("grounded!"); }
为您的 Animal() class 提供一个列出支持的操作的抽象方法,然后测试每个成员以查看它是否实现了 fly() 方法:
public abstract class Animal { private Set<String> behaviors; public Animal() { behaviors = new HashSet<String>(); } public Set<String> getBehaviors() { return behaviors; } } public class Dog extends Animal { public Dog() { super(); behaviors.add("fetch"); } public String fetch(String fetched) { return "Dog fetched " + fetched; } } public class Bird extends Animal implements Flyable { public Dog() { super(); behaviors.add("fly"); } @Override public String fly() { return "flap flap"; } } .... List<Animal> animals = MagicalAnimalListCreator.MakeAnimalList(); for (Animal animal : animals) { if (animal.getBehaviors().contains("fly")) { animal.fly(); } }
你可以按照你目前的方式来做,但是在尝试飞行之前尝试将你列表中的每个成员都投射到 Bird 并抓住 ClassCastException。如果施法成功,你就会得到一只鸟并且可以飞了。