我有 2接口:
public interface Flash { public void flash(int level); }
和
public interface SuperFlash extends Flash { public void flash(int level, boolean repeat); }
然后我有一个自定义集合类,它应该包含任意数量的实现Flash
或SuperFlash
的东西。 类声明类似于
public class FlashyThings<? extends Flash>
。
因此,类可以包含类型Flash
及其子类型的实例。
在课程FlashyThings
中,我使用 ArrayList
来保存所有这些对象:
private ArrayList<? extends Flash> things;
到目前为止一切顺利,现在,当我尝试迭代集合时,有没有办法知道/推断对象的动态类型而不使用instanceof
(如下一个片段)?
for (Flash f : this.things) {
if (f instanceof SuperFlash) { // <-- :(
// SuperFlash things
} else {
// Flash things
}
}
这是奖牌的上限,现在是下边界
首先,我必须将类声明更改为
public class FlashyThings
因为类声明中不允许使用较低的有界通配符。 ArrayList
声明现在看起来像:
private ArrayList<? super SuperFlash> things;
现在迭代整个集合变为:
for (Object o : this.things) { // <-- :((
// All things are of type Object which is *really* not cool
if (o instanceof SuperFlash) { // <-- :(
// SuperFlash things
} else {
// Flash things
}
}
所以我几乎陷入了我开始的地方。
迭代这样一个构造的推荐方法是什么?总而言之,我想要实现的目标是
FlashyThings
是可参数化的ArrayList things
,考虑其内容的动态类型(无需进行instanceof
检查)答案 0 :(得分:2)
你需要做的是创建一个抽象的FlashyThing,它在抽象类中尽可能多地执行共享方法,只留下依赖于知道你有子类的Flash或SuperFlash的东西。例如(为简洁而遗漏的公众和私人):
abstract class AbstractFlashyThing<F extends Flash> {
List<F> flashes;
AbstractFlashyThing() {
flashes = new ArrayList<F>();
}
void doOperations() {
for (F flash : flashes) {
doOperation(flash);
}
}
abstract void doOperation(F flash);
}
请注意通用类型F
如何尽可能用作占位符。
示例子类
class SuperFlashyThing extends AbstractFlashyThing<SuperFlash> {
@Override
void doOperation(SuperFlash superFlash) {
// do super flash stuff
}
}
子类是一个具体的实现而不是泛型类,因此它的实例如下。
SuperFlashyThing thing = new SuperFlashyThing();
// as opposed to the following
SuperFlashyThing<SuperFlash> thing = new SuperFlashyThing<SuperFlash>();
答案 1 :(得分:0)
也许我不太了解这个问题,但为什么你要把一切变得如此复杂,而不仅仅是使用多态?这就是面向对象范式的目的。例如:
<强> Flash.java 强>
public class Flash {
public void doSomething() {
System.out.println("Flash doSomething()");
}
}
<强> SuperFlash.java 强>
public class SuperFlash extends Flash {
@Override
public void doSomething() {
System.out.println("SuperFlash doSomething()");
}
}
<强> FlashyThings.java 强>
public class FlashyThings {
private ArrayList<Flash> things = new ArrayList<>();
public ArrayList<Flash> getThings() {
return things;
}
public void doSomething(){
for (Flash thing : things) {
thing.doSomething();
}
}
}
<强> ExampleMain.java 强>
public class ExampleMain {
public static void main(String[] args) {
Flash first = new Flash();
SuperFlash second = new SuperFlash();
Flash third = new Flash();
FlashyThings things = new FlashyThings();
things.getThings().add(first);
things.getThings().add(second);
things.getThings().add(third);
things.doSomething();
}
}
答案 2 :(得分:0)
如何使用enum
?
public enum FlashType
{
Flash, SuperFlash;
}
添加一种方法,用于检查Flash
类型的任何对象的闪存类型:
public interface Flash
{
void flash(int level);
FlashType getType();
}
然后迭代private ArrayList<? extends Flash> things;
for (Flash f : this.things)
{
if (f.getType() == FlashType.SuperFlash)
{
// SuperFlash things
}
else if (f.getType() == FlashType.Flash)
{
// Flash things
}
}
或迭代ArrayList<? super SuperFlash> things;
for (Object o : this.things)
{
final Flash f = (Flash)o;//this cannot failed: SuperFlash extends Flash
if (f.getType() == FlashType.SuperFlash)
{
// SuperFlash things
}
else if (f.getType() == FlashType.Flash)
{
// Flash things
}
}