2013-07-22 17 views
1

不同类型(相同的接口)我有2类实现这样相同的接口..计数用于ArrayList的

// Interface 
Interface ISomething { ... } 

// Class A 
class A implements ISomething { ... } 

// Class B 
class B implements ISomething { ... } 

然后在ArrayList<ISomething>我都A类的许多实例和B.

有没有一种方法可以单独计算A类和B类的出现次数,而不使用instanceof。我绑定了很多方法(比如在A类和B类中创建新的方法,让他们决定是否应该增加保存在传递给它们的整数数组中的计数变量),但它们似乎并不是很好的设计。

PS。对不起,我的英语和Java和OO设计缺乏技能。如果这是一个不好的问题,请让我知道。

UPDATE
我试图visitor_pattern和它的工作(这比我之前所使用的方法更容易维护)。
的代码是这样的..

// Interfaces 
Interface ISomething { public void accept(ISomethingVisitor visitor); } 
Interface ISomethingVisitor { 
    public void visit(A a); 
    public void visit(B b); 
} 

// Classes 
class A implements ISomething { 
    @Override 
    public void accept(ISomethingVisitor visitor) { visitor.visit(this); } 
} 
class B implements ISomething { 
    @Override 
    public void accept(ISomethingVisitor visitor) { visitor.visit(this); } 
} 
class SomethingCountVisitor implements ISomethingVisitor { 
    private int aCount; 
    private int bCount; 

    @Override 
    public void visit(A a) { aCount++; } 
    @Override 
    public void visit(B b) { bCount++; } 
    //getters for aCount, bCount 
} 

// Example usage 
// Assuming items have many A and B instances. 
ArrayList<ISomething> items = new ArrayList<ISomething>(); 
... 
SomethingCountVisitor scVisitor = new SomethingCountVisitor(); 
for (ISomething item in items) 
    item.accept(scVisitor); 
+1

问:为什么你有ISomething,并在你需要算多少各亚型istances存在同一时间的列表?在我看来,A和B的2个列表会更好 –

+1

关心它是哪个类可能是不可取的,但如果那是最重要的,instanceof就是找出问题的简单而直接的方法。为什么要避免它? –

+0

添加新元素时,我希望只要它实现ISomething,新元素的类型无关紧要。这是一个糟糕的设计? –

回答

0

如果你不想使用instanceof你只能使用A.class.isInstance(Object)

0

谷歌的番石榴的工具为您服务。 https://code.google.com/p/guava-libraries/

ArrayList<ISomething> myList = ... 
Iterable<A> iterableOfAs = Iterables.filter(myList, A.class); 
int numOfAs = Iterables.size(iterableOfAs) 

我强烈建议你的项目使用番石榴。它可以提高您的效率几个数量级。将它添加到项目中对于基于jar的项目或者maven管理的项目来说都很简单。

+0

谢谢你的建议。我会尝试。 –

0

如果你永远只有两班,在接口声明的方法:

boolean isAnA(); 

实现它在A类返回true,在B类假。使用其结果来决定要增加哪个计数器。

如果可能有两个以上的类,则返回一个枚举。

但是,这一切都是非常间接的。如果你真的关心它是哪一类的话,instanceof是直接简单的方法来提出这个问题。

+0

是的,不幸的是这是一个非常容易出错的解决方案。 – allprog

+0

如果您的界面需要了解其实现者的任何信息,那么这是糟糕的设计。 –

0

答案很简单,没有。因为泛型只在编译时存在,而不是运行时。他们是安全措施,添加什么以及不添加什么。但是一旦代码编译完成,ArrayListArrayList<I>之间没有区别。

不计算使用instanceof,你不能检查那里有什么!

+1

如果A和B是参数化类,但答案是肯定的,但是你没有。在这种情况下,问题完全有效。 – allprog

0

您可以使用分类相等。

class Category<T> { 
    private Class<T> klazz; 

    public Category(Class<T> klazz) { 
     this.klazz = klazz; 
    } 

    @Override 
    public boolean equals(Object obj) { 
     return obj != null && klazz.equals(obj.getClass()); 
    } 
} 

System.out.println("#A : " + Collections.frequency(list, new Category(A.class))); 
System.out.println("#B : " + Collections.frequency(list, new Category(B.class))); 

(在Java 8中的解决方案将变得更直接。)