检测实现接口的对象的类

时间:2022-09-02 12:01:30

I'm writing a game, as part of this players should be able to click on various GUI items and see further details on a specific area of the GUI. I'm mangaing this through an interface Detailable which is implemented by suitable game obects and sends the appropriate information to the JPanel

我正在编写游戏,因为玩家应该可以点击各种GUI项目并查看GUI特定区域的更多详细信息。我通过一个由适当的游戏对象实现的界面Detailable来对此进行漫画,并将相应的信息发送给JPanel

There are also containers (all of which implement Detailable) that contain other (Detailable implementing) objects. The goal being it is possible to click on a container and, amongst its stats, see its contents which can then be in turn clicked on to see their stats, etc.

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

The problem I am having is in writing the addToContents(Detailable d) method of my containers. Each container as an ArrayList<String> of the "type" of container - wardrobe, bookcase, etc. I want to be able to add only certain classes to a given container - so a container with a type of "bookcase" will only accept objects of class Book or Curio for example.

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

What I currently have is:

我现在拥有的是:

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;
        }
    }

But this feels like the wrong way of doing it. Is there a better way? Ideally, for sake of easy code, I'd have something like (pseudocode)

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

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

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

but I can't seem to find a way of adding a list of classes to the constructor - of translating the ArrayList of class names to an ArrayList of references to the actual class.

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


Containers are currently read from a JSON so comprise two classes:

目前,容器是从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);
}

2 个解决方案

#1


0  

If I understand your question correctly, you are looking for something like this

如果我正确理解你的问题,你正在寻找这样的东西

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

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

and then do something akin to

然后做类似的事情

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

to check if the instance is of an acceptable type

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

#2


2  

You can actually use a Map as shown below:

您实际上可以使用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
 }  

#1


0  

If I understand your question correctly, you are looking for something like this

如果我正确理解你的问题,你正在寻找这样的东西

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

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

and then do something akin to

然后做类似的事情

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

to check if the instance is of an acceptable type

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

#2


2  

You can actually use a Map as shown below:

您实际上可以使用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
 }