简体   繁体   English

从存储为超类Java的子类访问方法(向下转换?)

[英]Accessing methods from subclass stored as superclass Java (downcasting?)

I'm working on an inventory program in Java. 我正在使用Java开发清单程序。 I have each object in the inventory stored as a relavent class type in a DefaultListModel and JList for each location; 我将清单中的每个对象存储为每个位置的DefaultListModelJList的相关类类型; for example, if I have a video called "Mulan" and a generic thing called "Ball" in a location "Dorm", in the JList called "Dorm", "Mulan" will be an instance of video and "Ball" will be an instance of thing . 例如,如果我在“宿舍”位置有一个名为“ Mulan”的视频和一个名为“ Ball”的通用对象,则在JList “ Dorm”中,“ Mulan”将是video一个实例,而“ Ball”将是thing一个实例。 All the classes are inherited from thing. 所有的类都是从事物继承的。

I'm trying to do something like this... 我正在尝试做这样的事情...

Dorm.getSelectedValue().methodInVideoOrThing;

...but when I try it, it says: ...但是当我尝试时,它说:

error: cannot find symbol
      Dorm.getSelectedValue().methodInVideoOrThing();
                             ^
symbol:   method methodInVideoOrThing()
location: class Object

Because the DefaultListModel stores each object in a generic object variable, I'm not able to access the methods for any of the classes I made. 因为DefaultListModel将每个对象存储在通用object变量中,所以我无法访问所创建的任何类的方法。 I tried this... 我试过了

class c = Dorm.getSelectedValue().getClass();
c A = (c) Dorm.getSelectedValue();
A.methodInC;

... but it returned the following error: ...但是它返回以下错误:

error: cannot find symbol
      c A = (c) Dorm.getSelectedValue();
      ^
symbol: class c

error: cannot find symbol
      c A = (c) Dorm.getSelectedValue();
             ^
2 errors
symbol: class c

I know I could just cycle through all the classes using isInstanceOf and downcast on a case by case basis, but that would be quite tedious. 我知道我可以使用isInstanceOf循环遍历所有类,并逐个案例进行向下转换,但这将非常乏味。 Plus, when I do... 另外,当我这样做时...

System.out.println(Dorm.getSelectedValue().getClass());

...it returns either class video or class thing , depending on whether "Ball" or "Mulan" is selected, so I know that java knows what class it is. ...根据选择的是“ Ball”还是“ Mulan”,它返回class videoclass thing ,所以我知道java知道它是什么类。

So, is there some way I can access the methods of a subclass, when that subclass is stored as a variable of type object, without downcasting? 因此,当该子类存储为类型为object的变量而无需向下转换时,有什么方法可以访问该子类的方法? Or is there a way to do this with downcasting and I'm just doing it wrong? 还是可以通过向下转换来做到这一点,而我只是做错了?

as such there is no way to use sub-type methods from super-type other than down-casting. 因此,除了向下转换之外,没有办法使用超类型的子类型方法。 so better u could set up a if-else ladder 这样更好,您可以设置一个if-else阶梯

if (o instanceof Type1)
{
((Type1)0)MethodOfType1
}
else if
{
...
}

But in my opinion, i would rather prefer to add 1 more level of class above your things & video, and provide a generic method for things and video. 但是我认为,我宁愿在您的事物和视频之上再增加一个级别的类,并为事物和视频提供通用的方法。

The issue here is with your Object Oriented design. 这里的问题与您的面向对象设计有关。 What kind of method is "methodInVideoOrThing()"? methodInVideoOrThing()是什么方法? If this is a method that all things (including video's) have in common then it belongs in Thing. 如果这是所有事物(包括视频)共有的方法,则它属于Thing。 If it is a video-specific method then it belongs in Video. 如果是视频特定的方法,则它属于视频。

In the first case (method of Thing) you can just cast the value from JList to Thing and you're done: 在第一种情况下(Thing的方法),您可以将值从JList强制转换为Thing,然后完成:

Thing selectedThing = (Thing) dorm.getSelectedValue();
selectedThing.methodInThing();

In the second case (method of Video) you have the problem you described of having to distinguish between different categories of Things like Videos, Fruit and Clothing. 在第二种情况下(视频方法),您遇到的问题是必须区分不同类别的事物,例如视频,水果和服装。 What I think I would do in this case is create separate classes to handle each category and pass the Object to it based on its category, a simple example: 在这种情况下,我想做的是创建单独的类来处理每个类别,并根据其类别将Object传递给它,这是一个简单的示例:

public interface Handler {
    public Class getCategory();
    public void handle(Thing item);
}

public class VideoHandler implements Handler {
    public Class getCategory() {
        return Video.class;
    }

    public void handle(Thing item) {
        if (!item instanceof getCategory()) {
            throw new IllegalArgumentException("Wrong category - can only handle Video");
        }
        Video video = (Video) item;
        // do video-things            
    }        
}

In your calling class you need to select the correct handler based on the category: 在调用类中,您需要根据类别选择正确的处理程序:

private void init() {
    List<Handler> handlers = new ArrayList<Handler>();
    handlers.add(new VideoHandler());
    // add other handlers
}

public void someMethod(Jlist dorm) { 
    Object item = dorm.getSelectedValue();
    for(Handler handler : handlers) {
        if (item instanceof handler.getCategory()) {
            // optionally catch IllegalArgumentException here 
            handler.handle(item);
        }
    }
}

This can be made a bit nicer, for example use an enum as Category instead of the class, use generics to type the Handler and extract any common behavior (like the typechecking) into an abstract class, but this is the gist of it. 这可以做得更好一些,例如,使用枚举作为Category代替类,使用泛型键入Handler并将任何常见行为(如类型检查)提取到抽象类中,但这是它的要旨。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM