【问题标题】:Detecting Class of an object implementing an interface检测实现接口的对象的类
【发布时间】:2017-09-11 05:42:35
【问题描述】:

我正在编写一个游戏,作为游戏的一部分,玩家应该能够点击各种 GUI 项目并查看 GUI 特定区域的更多详细信息。我正在通过一个接口Detailable 来管理它,该接口由合适的游戏对象实现,并将适当的信息发送到JPanel

还有包含其他(Detailable 实现)对象的容器(所有这些都实现了Detailable)。目标是可以单击容器并在其统计信息中查看其内容,然后依次单击以查看它们的统计信息等。

我遇到的问题是编写容器的addToContents(Detailable d) 方法。每个容器作为容器“类型”的ArrayList<String> - 衣柜、书柜等。我希望能够只向给定容器添加某些类 - 所以具有“书柜”类型的容器将只接受对象例如 BookCurio 类。

我目前拥有的是:

public boolean addToContents(Detailable d){
        if(this.types.contains("bookcase") && d.getClass().getName().equals("Book")){
            //do some stuff
            //I know "Book" isn't the right syntax, this is just to demo
            return true;
        }
        else if(this.types.contains("bookcase") && d.getClass().getName().equals("Curio")){
            //other stuff
            return true;
        }
        //etc
        else{
             return false;
        }
    }

但这感觉像是错误的做法。有没有更好的办法?理想情况下,为了简单的代码,我会有类似(伪代码)

Constructor:
private ArrayList<Class> classesAccepted = <list of classes>

addToContents:
if (classesAccepted.contains(d.getClass()){
    add the thingie to contents
    return true
}
else{
     return false;
}

但我似乎找不到将类列表添加到构造函数的方法 - 将类名的 ArrayList 转换为对实际类的引用的 ArrayList。


容器目前是从 JSON 中读取的,因此包含两个类:

public class FurnitureType {
    private String name;
    private List<String> type;
    private int cost;
    private String description;
    private int comfortBonus;
    private int capacity;
    //plus getters for all the above
}

public class Furniture implements Detailable, ListSelectionListener{

private String name;
private List<String> types;
private int cost;
private String description;
private int comfortBonus;
private int capacity;
private ArrayList<Detailable> contents;
private transient DetailPanel dp = null;

public Furniture (FurnitureType type){
    this.name=type.getName();
    this.types = type.getType();
    this.cost = type.getCost();
    this.description = type.getDescription();
    this.comfortBonus = type.getComfortBonus();
    this.capacity = type.getCapacity();
    this.contents = new ArrayList();
}
//appropriate getters

public boolean addToContents(Detailable d){
        if(this.types.contains("bookcase") && d.getClass().getName().equals("Book")){
            //do some stuff
            //I know "Book" isn't the right syntax, this is just to demo
            return true;
        }
        else if(this.types.contains("bookcase") && d.getClass().getName().equals("Curio")){
            //other stuff
            return true;
        }
        //etc
        else{
             return false;
        }
    }
@Override
public String toString(){
    return description;
}

@Override
public Icon getBigPic() {
    return null;
}

@Override
public JComponent getStats() {
    Object [] objectContents = contents.toArray();
    JList contentList = new JList(objectContents);
    contentList.setPreferredSize(new Dimension (400, 300));
    contentList.setFixedCellHeight(50);
    contentList.addListSelectionListener(this);
    contentList.setCellRenderer(new CustomCellRenderer());
    //the CustomCellRenderer class simply makes long descriptions into multiline cells
    return contentList;
}

@Override
public void addPanel(DetailPanel dp) {
    this.dp = dp;
}

@Override
public void valueChanged(ListSelectionEvent lse) {
    Detailable d = contents.get(lse.getFirstIndex());
    dp.updatePanel(d);
}

【问题讨论】:

  • 你的伪代码几乎就在那里,对吧?有什么问题?
  • 抱歉,为了清楚起见,我会更新问题 - 你是对的,我没有特别明确地说明问题
  • Book 和 Curio 有共同的超类型吗?
  • 他们没有,但如果这是一个更简单的解决方案,他们可以拥有。目前两者都没有扩展任何东西
  • 你能告诉我们你目前的容器是什么样子吗?

标签: java class implements


【解决方案1】:

如果我正确理解您的问题,您正在寻找类似的东西

ArrayList <Class<? extends Detailable>> acceptedClasses = new ArrayList<>();

acceptedClasses.add(Bookcase.class);
acceptedClasses.add(OtherAcceptable.class);

然后做类似的事情

boolean test = 
    acceptedClasses.stream().anyMatch(clazz -> aClass.isInstance(detailableInstance));

检查实例是否是可接受的类型

【讨论】:

  • 简单的 new ArrayList&lt;&gt;() 在 Java 7+ 中应该没问题
  • Federico,我真的应该先通过编译器运行它。感谢您指出这一点,修复了 class 与 clazz 的错字并处理了布尔问题。干杯:)
【解决方案2】:

您实际上可以使用Map,如下所示:

private static Map<String, List<Class<? extends Detailable>>>
       bookcaseContainer = new HashMap<>();

 static {
       //load the bookcaseContainer Map from properties/database
         bookcaseContainer.put("bookcase", list1);
         bookcaseContainer.put("wardrobe", list2);
    }


if(bookcaseContainer.get("bookcase") != null && 
        bookcaseContainer.get("bookcase").contains(d.getClass())) {
        //do something here
 } else if(bookcaseContainer.get("wardrobe") != null && 
        bookcaseContainer.get("wardrobe").contains(d.getClass())) {
        //do something here
 }  

【讨论】:

  • 很好的答案,感谢您的帮助。接受另一个,因为代码略短,我不能接受两个,但它是一个不错的解决方案。
猜你喜欢
  • 2010-12-17
  • 1970-01-01
  • 2010-10-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-04-07
  • 1970-01-01
相关资源
最近更新 更多