示例如下:我有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());
}
}
}
答案 0 :(得分:2)
我真的没有得到你想要实现的目标。首先,我没有使用接口ThingId
。其次,我认为你对接口和继承有点困惑。如果我是你,我会抬头polymorphism。
无论如何,我建议你删除ThingId
接口,让FruitId
和ToyId
类扩展Thing
类。由于您的收藏只存在Thing
s,并且您的Fruit
和Toy
类都扩展了此Thing
类,因此实施getWeight()
方法,您应该不再使用instanceof
。
但是,请阅读polymorphism。
答案 1 :(得分:1)
您的界面ThingId
必须提供您想要的相应方法。
如果您只想打印出信息,那么您可以像简单的一样使用
public String getInformation();
然后,实现可以返回与它们相关的信息,您只需在应用程序代码中使用ThingId
即可。
顺便说一句:当您将Thing
存储在HashSet
时,请确保在所有equals
实施中实施hashCode
和Thing
另外,我真的没有看到,为什么你需要一个Thing
和一个ThingId
,因为ThingId
似乎不仅仅是一个简单的id而且实际上是一个东西。所以对我而言,似乎ThingId
是多余的,所有这些都可以通过具有不同的Thing
s来实现
答案 2 :(得分:1)
由于您在两个实例类型上调用相同的方法process
,为什么不将该方法添加到ThingId
接口本身。
通过这样做,你可以打电话:
t.getThingId().process();
而不是查找实例类型并调用相应的方法。