您好我想知道这样的更优雅的替代品会是什么:
class Base...
class A extends Base...
class B extends Base...
//iterator of colection containing mixed As and Bs i want to remowe Bs and do omething with As
while(iterator.hasNext()) {
Base next = iterator.next();
if(next instanceof A) // do something
if(next instanceof B)
iterator.remove();
}
播种有哪些替代品......
感谢您的建议。
编辑:基类可能有许多子类,而不只是两个,它们的数字可能会及时增长
答案 0 :(得分:1)
您可以在Base
中创建方法,并在A
和B
中覆盖它们。
例如:
class Base{
public boolean shouldRemove(){
return false;
}
public void doSomething(){
}
}
class A extends Base{
@Override
public void doSomething() {
}
}
class B extends Base{
@Override
public boolean shouldRemove() {
return true;
}
}
然后你不需要知道对象是一个实例的类:
while(iterator.hasNext()) {
Base next = iterator.next();
if(next.shouldRemove()){
iterator.remove();
}
else{
next.doSomething();
}
}
答案 1 :(得分:1)
你真的需要从列表中删除它们吗?你为什么不只是在Base
类中做某事(无所事事),然后只是将它覆盖到你想要的类A
上。
class Base{
public void doSomething(){
}
}
class A extends Base{
@Override
public void doSomething(){
// do something
}
}
然后你可以遍历列表并在所有对象上调用方法doSomething。
for(Base base : list) {
base.doSomething();
}
这样只有覆盖doSomething()
方法的类才能实际执行某些操作。所有其他类只会在Base类中执行虚拟实现。
如果Base
是一个抽象类,您可以将doSomething()
声明为抽象类,并让扩展类实现它。使用这种方法,所有类都必须实现您不希望执行任何计算的方法和类,您只需提供该方法的虚拟实现。或者,您甚至可以使用doSomething()
方法创建一个接口并且具有(甚至可以做出更好的决策)并让Base
类实现它,因为只有扩展类才会实际实现该方法。
答案 2 :(得分:0)
我认为这是一个非常简短明了的解决方案,没有替代方案(没有代码增长),
只需在第二种情况下添加else if
而不是if
此外,您可以在函数调用上拆分代码,if语句也不会很大
另一个解决方案是创建将被调用的Map
个委托。像这样:
interface ISimpleDelegate{ void doSomeLogic(Base b) }
`Map delegates = new HashMap();
之后,将您的逻辑添加为实现ISimpleDelegate的匿名类。
delegates.put(A.class, new ISimpleDelegate() { //write your logic here });
我希望这个想法很明确
在您的循环中,您只需致电代表:
while(iterator.hasNext()) {
Base next = iterator.next();
delegates.get(next.getClass()).doSomeLogic(next);
}
答案 3 :(得分:0)
instanceof
是按类型过滤对象的好方法 - 这就是你想要做的事情。你有一个混合集合,所以你需要某种过滤器,过滤输入(只存储A
s)或过滤输出(只处理A
s)。
如果您不喜欢“instanceof”,可以使用enum
指定类型并添加最终方法以获取Base
处的类型:
enum Type { ATYPE, BTYPE };
public Base {
final private Type type;
public Base(Type type) { this.type = type; }
public Type getType() { return type; }
// ...
}
public A {
public A() { super(Type.ATYPE); }
}
while(iterator.hasNext()) {
Base next = iterator.next();
switch (next.getType) {
case ATYPE: // do something and break
case BTYPE: iterator.remove(next); break;
}
}
答案 4 :(得分:0)
一般来说,避免instanceof
的好方法是使用所谓的visitor pattern。
对于此模式,您需要一个额外的接口(Visitor),它的实现包含您要执行的代码以及层次结构的所有类中的其他方法,因此在小的情况下这可能是过度的(但是如果不仅A
和B
,还有更多类型,那么它非常方便。
在你的情况下,它看起来像这样:
interface Visitor {
void visit(A a);
void visit(B b);
}
class Base {
abstract accept(Visitor v);
}
class A extends Base {
accept(Visitor v) {
v.visit(this);
}
}
class B extends Base {
accept(Visitor v) {
v.visit(this);
}
}
class MyVisitor implements Visitor {
visit(A a) {
doSomethingWithA(a);
}
visit(B b) {
doSomethingWithB(b);
}
}
它的用法如下:
MyVisitor v = new MyVisitor();
while(iterator.hasNext()) {
Base next = iterator.next();
next.accept(v);
}
一个优点是你必须只编写一次大部分代码。如果你想在程序的另一个地方用A和B做其他事情,那就写下另一个Visitor实现。您无需修改Base
,A
和B
,就像您将doSomething()
添加到这些类中一样。
修改强>
如果子类的数量增加,则需要更改Visitor
的所有现有实现。但是,至少编译器会告诉你这一点。使用instanceof
,您可能最终忘记了需要添加处理子句的位置。这最多可以在运行时检测到,而访问者模式可以为您提供编译时的安全性。