简体   繁体   中英

Is there a compiler-safe way to access a member field of an Object when its class is not known at compile-time?

I am currently creating a class, which has a field of Object type.

My issue is that when accessing a member of this object, the compiler throws a Symbol not found error, as the class is not known at compile-time. Is there a way to ignore this, or mark it as resolve later, ie at runtime?

Specifically: I have a linked list that collects a list of classes, which store information about UI controls, as well as storing a reference to the real UI control (this being the Object field as obj). The Object (obj) has a hitbox member (hb), which I am trying to set a property of.

The offending line is:

items.get(this.curIndex).obj.hb.hovered=true;

As I am not at liberty to publish the source, here's a mockup for easier understanding of what's happening.

public class MenuButton {
    public HitBox hb;
    ...
}

public class NameEdit {
    public HitBox hb;
    ...
}

public class VolumeSlider {
    public HitBox hb;
    ...
}

public class HitBox {
    public Boolean hovered;
    ...
}

public class AObject {
    public String label;
    public String hint;
    public Object obj;
    ...
}

public class AContainer {
    public LinkedList<AObject> items=new LinkedList<>();

    public void add(Object obj) {
        items.add(obj);
    }
    ...
}

//elsewhere:
    public LinkedList<AContainer> containers=new LinkedList<>();
    ...
    containers.get(0).items.get(0).obj.hb.hovered=true;

What this comes down to is that AObject has an obj member, which the compiler cannot infer the class of, thus I get a cannot find symbol, since Java cannot check at compile-time that when obj is set, it's going to have a hb field.

Any help is greatly appreciated.

You can change the class AObject to use a generic type for the type for obj . It might look like this:

public class AObject<T> {
    public String label;
    public String hint;
    public T obj;
    // [...]]
}

Then you add a new interface for objects which have a hitbox.

public interface HasHitBox {
    public HitBox getHitBox();
}

Your classes MenuButton , NameEdit and VolumeSlider will implement this interface. Then you can change the field

public LinkedList<AObject> items=new LinkedList<>();

to

public LinkedList<AObject<HasHitBox>> items=new LinkedList<>();

Now you can add AObject objects which reference an object, which implements the HasHitBox interface. And that gives you the ability to call getHitBox() .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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