[英]Looping over heterogeneous collection
示例如下:我有一个Box
,需要填充一些Thing
。 我只对每件东西的重量感兴趣。 另外,除了体重,我还需要正确识别正在测量的东西。 每种事物类型都有不同的ID类型。 在这种情况下,我有玩具和水果,它们分别具有ToyId
和FruitId
。 最后,我需要能够打印事物标识符和事物权重。
问题:是否可以在不使用instanceof运算符的情况下以某种方式访问ThingId
的特定方法?
class Color{}
interface ThingId {}
class FruitId implements ThingId {
String name; //"apple", "orange", ...
FruitId(String name){ this.name = name; }
String getName(){ return this.name; }
}
class ToyId implements ThingId {
String shape; //"square", "circle", ...
Color color; //"red", "blue"...
ToyId(String shape, Color color){ this.shape = shape; this.color = color; }
String getShape(){ return this.shape; }
Color getColor(){ return this.color; }
}
class Thing{
ThingId thingId;
Integer weight;
public Thing(ThingId thingId, Integer weight){
this.thingId = thingId;
this.weight = weight;
}
ThingId getThingId(){ return this.thingId; }
Integer getWeight(){ return this.weight; }
}
class Box {
Set<Thing> things = new HashSet<>();
void addThing(Thing thing){
this.things.add(thing);
}
Collection<Thing> getThings(){
return this.things;
}
}
class Program {
public static void main(String[] args) {
FruitId appleId = new FruitId("apple");
Thing apple = new Thing(appleId, 1);
ToyId cubeId = new ToyId("square", new Color());
Thing cube = new Thing(cubeId, 22);
Box box = new Box();
box.addThing(apple);
box.addThing(cube);
for(Thing t : box.getThings()){
System.out.print("Thing Id is: ");
if(t.getThingId() instanceof FruitId) { //any other possibility than using instance of?
process((FruitId)t.getThingId());
}
if(t.getThingId() instanceof ToyId){ //any other possibility than using instance of?
process((ToyId)t.getThingId());
}
System.out.println("Weight is : " + t.getWeight());
}
}
static void process(FruitId fruitId){
System.out.println(fruitId.getName());
}
static void process(ToyId toyId){
System.out.println(toyId.getShape() + toyId.getColor());
}
}
更新
好的,我认为访客模式在这里可能有用:
class Color{}
interface ThingId {
void visitThingId(ThingIdVisitor visitor);
}
class FruitId implements ThingId {
String name; //"apple", "orange", ...
FruitId(String name){ this.name = name; }
String getName(){ return this.name; }
@Override
public void visitThingId(ThingIdVisitor visitor) {
visitor.process(this);
}
}
class ToyId implements ThingId {
String shape; //"square", "circle", ...
Color color; //"red", "blue"...
ToyId(String shape, Color color){ this.shape = shape; this.color = color; }
String getShape(){ return this.shape; }
Color getColor(){ return this.color; }
@Override
public void visitThingId(ThingIdVisitor visitor) {
visitor.process(this);
}
}
class Thing{
ThingId thingId;
Integer weight;
public Thing(ThingId thingId, Integer weight){
this.thingId = thingId;
this.weight = weight;
}
ThingId getThingId(){ return this.thingId; }
Integer getWeight(){ return this.weight; }
}
class Box {
Set<Thing> things = new HashSet<>();
void addThing(Thing thing){
this.things.add(thing);
}
Collection<Thing> getThings(){
return this.things;
}
}
class ThingIdVisitor{
void process(FruitId fruitId){
System.out.println(fruitId.getName());
}
void process(ToyId toyId){
System.out.println(toyId.getShape() + toyId.getColor());
}
}
class Program {
public static void main(String[] args) {
FruitId appleId = new FruitId("apple");
Thing apple = new Thing(appleId, 1);
ToyId cubeId = new ToyId("square", new Color());
Thing cube = new Thing(cubeId, 22);
Box box = new Box();
box.addThing(apple);
box.addThing(cube);
for(Thing t : box.getThings()){
System.out.print("Thing Id is: ");
t.getThingId().visitThingId(new ThingIdVisitor());
System.out.println("Weight is : " + t.getWeight());
}
}
}
您的界面ThingId
必须提供您想要的相应方法。
如果您简单地想打印出信息,那么您可以像简单地使用
public String getInformation();
然后,实现可以返回与其相关的信息,您只需在应用程序代码中使用ThingId
。
顺便说一句:当您将Thing
存储在HashSet
确保在所有Thing
实现中实现equals
和hashCode
我也真的看不出来,为什么需要Thing
和ThingId
,因为ThingId
似乎不仅仅是一个简单的id,而是一个实际的东西。 所以对于我来说, ThingId
似乎是多余的,并且可以通过拥有不同的Thing
来实现
由于您要在两种实例类型上调用相同的方法process
,因此为什么不将该方法添加到ThingId
接口本身。
这样,您可以致电:
t.getThingId().process();
而不是查找实例类型并调用各自的方法。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.