如何使用instanceof语句动态转发对象? 我在阅读Bruce Eckel的Thinking in Java,并且使用了Class,并且有这样一个主题,但我没有接近 附:抱歉我的英文。
public class GenericTest {
static private interface Base {
}
static private class A implements Base {
}
static private class B implements Base {
}
static private class C extends B {
}
private List<Class<? extends Base>> types;
private List<Base> objects;
public GenericTest() {
types = new ArrayList<Class<? extends Base>>();
types.add(A.class);
types.add(B.class);
types.add(C.class);
objects = new ArrayList<Base>(Arrays.asList(new A(), new B(), new C()));
for (Base base : objects) {
if (base instanceof A)
test((A) base);
else if (base instanceof C)
test((C) base);
else if (base instanceof B)
test((B) base);
for (Class<? extends Base> c : types)
if (base.getClass().equals(c))
test(c.cast(base));
}
}
private void test(A a) {
System.out.println("A");
}
private void test(B b) {
System.out.println("B");
}
private void test(C c) {
System.out.println("C");
}
private void test(Base base) {
System.out.println("Base");
}
public static void main(String[] args) {
new GenericTest();
}
}
答案 0 :(得分:3)
有时,使用instanceof
表示您的设计存在缺陷,可能违反了面向对象编程的一些基本原则。
在你的情况下,我可以监督两个解决方案,具体取决于你的最终目标。第一个是将test()
的特定行为封装在类A
,B
和C
中。可以通过在接口test()
中声明方法Base
,使其成为抽象类并在子类中实现它来完成。
static private abstract class Base {
public void test() {
System.out.println("Base");
}
}
static private class A extends Base {
private void test() {
System.out.println("A");
}
}
static private class B implements Base {
private void test() {
System.out.println("B");
}
}
static private class C extends B {
private void test() {
System.out.println("C");
}
}
请注意,层次结构级别大于3的类不是一个好习惯。继承是两个对象之间可以获得的最高耦合度。这就是为什么我们倾向于prefer composition over inheritance。
正如@SLaks所提到的,改进设计的第二种方法是使用访客模式。可以找到有关此模式的更多信息here。有关该主题的推荐阅读材料为GOF和Refactoring to Patterns。
答案 1 :(得分:2)
目前还不清楚你想做什么,但这里是你如何在没有施放和instanceof
的情况下获得相同的结果。
将test
方法放在接口Base
上:
static private interface Base {
public void test();
}
然后实施它:
static private class A implements Base {
public void test() {
System.out.println("A");
}
,同样适用于B
和C
。
然后你的循环应该是这样的:
for (Base base : objects) {
base.test();
}
如果A::test
是base
的实例,则会A
调用B::test
,如果base
是B
的实例,则会调用{{1}}。 (根据引用对象的运行时类型选择方法。)