使用仅在运行时可获得的静态类型
Use a static type only obtainable at runtime
假设我的情况如下:
A class X
有一个类型为 S
的字段 s
。
S
扩展了两个 classes A
和 B
都实现了一些相同的 methods/fields 我们都知道应该在 S
但不幸的是,情况并非如此。
现在我想做这样的事情:
"A or B" downcast_field;
if(s instanceof A)
downcast_field = (A)s;
else if (s instanceof B)
downcast_field = (B)s;
//do something common for the two cases but that need methods implemented both in A and B
然后问题是预先有一个静态类型(在 IFs
之外)允许我调用这些方法。
我想由于糟糕的设计,这实际上是不可能的,我必须编写两次相同的代码,这很丑陋,但也许有一个我现在没有看到的解决方案。
如果可以更改 A
和 B
,则可以为两者添加相同的界面。这将允许您将此类型提供给 downcast_field
并调用方法。
如果您无法更改 A
和 B
,那么您有两个选择:
可以写A2
和B2
。将 A
和 B
中的代码复制到新类型中。这允许您修改代码(除非您无法控制这些类型的创建)。或者,您现在也可以创建扩展 S
的 S2
并将通用代码放在那里,然后从中扩展 A2
/B2
。
创建一个接口,然后创建两个只将调用委托给实际类型的实现。
在此解决方案中,您可以
Wrapper downcast_field;
if(s instanceof A)
downcast_field = new AWrapper( (A)s );
else if (s instanceof B)
downcast_field = new BWrapper( (B)s );
downcast_field.foo();
您可以使这两个包装器扩展相同的类型并将公共代码移到那里。
据我了解你的情况是这样的?
public class S {
}
public class A extends S {
public void doSomething() {
System.out.println("A is doing something ...");
}
}
public class B extends S {
public void doSomething() {
System.out.println("B is doing something ...");
}
}
其实我觉得这个设计比较糟糕。如果你有机会
清理这个你应该这样做。如果这不是以下选项
解决方法是可能的......引入一个声明通用的接口API
并使用此接口包装您的实例 ...
public interface WrapperInterface {
void doSomething();
}
那么你可以像这样使用它
public class Main {
public static void main(String[] args) {
WrapperInterface a=wrap(new A());
WrapperInterface b=wrap(new B());
a.doSomething();
b.doSomething();
}
private static WrapperInterface wrap(final S s) {
WrapperInterface downcast_field=null;
if (s instanceof A)
downcast_field = new WrapperInterface() {
@Override
public void doSomething() {
((A) s).doSomething();
}
};
else if (s instanceof B) {
downcast_field = new WrapperInterface() {
@Override
public void doSomething() {
((B) s).doSomething();
}
};
}
return downcast_field;
}
}
假设我的情况如下:
A class X
有一个类型为 S
的字段 s
。
S
扩展了两个 classes A
和 B
都实现了一些相同的 methods/fields 我们都知道应该在 S
但不幸的是,情况并非如此。
现在我想做这样的事情:
"A or B" downcast_field;
if(s instanceof A)
downcast_field = (A)s;
else if (s instanceof B)
downcast_field = (B)s;
//do something common for the two cases but that need methods implemented both in A and B
然后问题是预先有一个静态类型(在 IFs
之外)允许我调用这些方法。
我想由于糟糕的设计,这实际上是不可能的,我必须编写两次相同的代码,这很丑陋,但也许有一个我现在没有看到的解决方案。
如果可以更改 A
和 B
,则可以为两者添加相同的界面。这将允许您将此类型提供给 downcast_field
并调用方法。
如果您无法更改 A
和 B
,那么您有两个选择:
可以写
A2
和B2
。将A
和B
中的代码复制到新类型中。这允许您修改代码(除非您无法控制这些类型的创建)。或者,您现在也可以创建扩展S
的S2
并将通用代码放在那里,然后从中扩展A2
/B2
。创建一个接口,然后创建两个只将调用委托给实际类型的实现。
在此解决方案中,您可以
Wrapper downcast_field; if(s instanceof A) downcast_field = new AWrapper( (A)s ); else if (s instanceof B) downcast_field = new BWrapper( (B)s ); downcast_field.foo();
您可以使这两个包装器扩展相同的类型并将公共代码移到那里。
据我了解你的情况是这样的?
public class S {
}
public class A extends S {
public void doSomething() {
System.out.println("A is doing something ...");
}
}
public class B extends S {
public void doSomething() {
System.out.println("B is doing something ...");
}
}
其实我觉得这个设计比较糟糕。如果你有机会 清理这个你应该这样做。如果这不是以下选项 解决方法是可能的......引入一个声明通用的接口API 并使用此接口包装您的实例 ...
public interface WrapperInterface {
void doSomething();
}
那么你可以像这样使用它
public class Main {
public static void main(String[] args) {
WrapperInterface a=wrap(new A());
WrapperInterface b=wrap(new B());
a.doSomething();
b.doSomething();
}
private static WrapperInterface wrap(final S s) {
WrapperInterface downcast_field=null;
if (s instanceof A)
downcast_field = new WrapperInterface() {
@Override
public void doSomething() {
((A) s).doSomething();
}
};
else if (s instanceof B) {
downcast_field = new WrapperInterface() {
@Override
public void doSomething() {
((B) s).doSomething();
}
};
}
return downcast_field;
}
}