1

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, i.e. 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.

Erion
  • 33
  • 1
  • 6
  • Is it an option to use generics? – Progman Jun 23 '20 at 18:02
  • Unfortunately not. As I understand, I would need to modify all the classes that *obj* can point to. Let me know if I am wrong though, generics weren't the first thing I thought of, having a Golang background ☺️ – Erion Jun 23 '20 at 18:15
  • @Erion You don’t need to modify the contained classes to use generics. You only need to modify your linked list class. Better yet, use Java’s built-in list class which already does this (and don’t use a linked list, it’s probably not what you want, linked lists are almost always worse that array-backed lists). – Konrad Rudolph Jun 23 '20 at 18:28
  • @Erion Please [edit] your question to include the source codes you have to show, where the problem is, where you have lists, how the UI is involved, where you use the `obj` field and how you want to access the hitbox member `hb`. – Progman Jun 23 '20 at 18:31
  • @konrad-rudolph Thanks for the tip. I am still not entirely sure how generics could help me, unfortunately, as I am chaining an assignment to an unknown, and to the compiler unexistent, member field. @Progman: I am unfortunately unable to share the exact source code, hence my very generic line. Essentially what it comes down to is that a variable (Object obj), has a hb (HitBox hb) field, which has a property (hb.hovered), which I'd like to modify. `obj.hb.hovered=true;` – Erion Jun 23 '20 at 18:44
  • @Erion The first attempt would be to change `Object obj` to `T obj`, where `T` is a generic type. But without the source code it's hard to tell how to solve it. – Progman Jun 23 '20 at 18:54
  • I see. This way I could still store any class in *obj*. The question is, would the compiler accept obj.hb.hovered=true, i.e. would it still throw an error if it can't infer that T, as a generic type, does not have *hb* as a member, which has a *hovered* property? – Erion Jun 23 '20 at 19:33
  • @Erion It will work when the generic type in that specific case will resolve to a type, which has a `hb` field, which uses a type which has a `hovered` field. The type `Object` does not have these properties. – Progman Jun 23 '20 at 19:40
  • Do I have to do anything specific, e.g. declare T as a specific type, such as *T*, when I'd like to access the *hb* field? If yes, this could be problematic, as I could have about a hundred different classes that an Object field could hold, all guaranteed to have a *hb* field with a type. – Erion Jun 23 '20 at 19:49
  • @Erion Does the `hb` field belong to a base class you can use? Can you use an interface which have a method like `getHitBox()` which would be implemented by the classes? It's very difficult to say or maybe too broad for how to solve the problem you have. Please [edit] your question to include source code which shows the problem you have, the different classes you use and how you want to connect them and access the data you have. – Progman Jun 23 '20 at 20:25
  • I am unfortunately unable to share the source, but I've edited my post to include a mockup. Hope this helps! – Erion Jun 23 '20 at 21:28
  • @Erion Btw.: You should use getters to access fields, not directly access them (and don't have them public), see https://stackoverflow.com/questions/1568091/why-use-getters-and-setters-accessors – Progman Jun 23 '20 at 21:39
  • Thank you. Yes, they are part of the original implementation, as of course it's not a good practice to access fields directly. – Erion Jun 24 '20 at 09:11

1 Answers1

0

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().

Progman
  • 16,827
  • 6
  • 33
  • 48