Getting a variable from an extended class [Solved]

So I have this array which contains UIElements (obviously);

public UIElement elements[] = {...}

and it contains classes that extend UIElements so that it’s easier for me to add and remove stuff;

public UIElement elements[] = {new Button("Back", 6, 104, 0), new SmallButton('<', 168, 32, 1), new SmallButton('>', 216, 32, 2), new SmallButton('C', 224, 64, 3),
        new Button("Embark", 186, 104, 4), new Textbox("Wayne Smith", 32, 32, 5), new Label("Name", 8, 32), new Label("Race", 8, 48), new Label("Gender", 8, 64),
        new Label("Clothing", 136, 48), new Label("Hair", 136, 64), new ArrayButton(new String[]{"Foreigner", "Native"}, 40, 48, 6),
        new ArrayButton(new String[]{"Male", "Female"}, 40, 64, 7), new ArrayButton(new String[]{"Dungaree", "Jacket", "Loincloth", "F.Loincloth"}, 173, 48, 8),
        new ArrayButton(new String[]{"Style A", "Style B"}, 173, 64, 9)};

For example; ArrayButtons store an array, an integer value and a scroll function (that changes that integer and sets the string on the button to show that element of the array)

HOWEVER, the problem is that I cannot simply;

player.race = elements[6].selection;
player.gender = elements[7].selection;
player.clothX = elements[8].selection / 2;
player.clothY = elements[9].selection % 2;
player.hairX = elements[10].selection;

Because the array contains UIElements, not ArrayButtons and I can’t access a variable that only exists in an ArrayButton

What can I do?

You’ll have to show us more code, particularly the class which creates the ui elements and it’s surrounding context. Post the whole class if it’s not too big.

Usually if one class creates an object of a particular type (eg. Button) and later needs to access specific info from that class (eg. Button.seletion) then you need to hold onto it as a reference to the specific type (eg. Button no UIElement).

package tumbleweed.ui.elements;

import org.newdawn.slick.Image;
import tumbleweed.Main;

public class UIElement {

    public int id;
    public float x, y;
    public int width, height;
    public String string;
    public Image image;
    public boolean isHovered;

    public void init() {
    }

    public void render() {
    }

    public void checkHovered(int x, int y) {
        if (x >= this.x * Main.SCALE && x <= this.x * Main.SCALE + width * Main.SCALE && y >= this.y * Main.SCALE && y <= this.y * Main.SCALE + height * Main.SCALE) {
            setHovered(true);
        } else {
            setHovered(false);
        }
    }

    public void setHovered(boolean value) {
        isHovered = value;
    }
}
package tumbleweed.ui.elements;

import org.newdawn.slick.Color;
import tumbleweed.ui.Screen;

public class ArrayButton extends UIElement {

    public String options[];
    public int selection;

    public ArrayButton(String options[], float x, float y, int id) {
        this.options = options;
        this.x = x;
        this.y = y;
        this.id = id;
    }
    
    public void init() {
        image = Screen.button;
        width = image.getWidth();
        height = image.getHeight();
    }
    
    public void render() {
        Color color = isHovered ? Palette.LABEL_YELLOW : Palette.LABEL_WHITE;

        Screen.drawImage(image, x, y, 1);

        Screen.drawFont(options[selection], x + (12 - options[selection].length()) * 2, y + (height - 4) / 2, color);
    }

    public void scrollOption(boolean forward) {
        selection = forward ? selection + 1 : selection - 1;

        if (selection >= options.length) {
            selection = 0;
        } else if (selection < 0) {
            selection = options.length - 1;
        }

        string = options[selection];
    }
}

I used to have tons of arrays for each object but it turned out to be a huge mess and I tried doing this but it really doesn’t help me at the moment

You can do something like this:


UIElement el = elements[index];
if (el instanceof  ArrayButton){
    ((ArrayButton)el).<ArrayButtonVar>
}

((ArrayButton)el).<ArrayButtonVar>

Was the part I needed that you aaaaalllot

Nope,

((ArrayButton)elements[6]).<selection>

didn’t work, getting identifier expected error from Netbeans

kill it with fire

-casts should nearly never be used
-why do u use an array, when you want to access single elements

I only tell you what you did wrong in the last post, when you swear to not use it^^
((ArrayButton)elements[6]).selection

Sry but i don’t have time atm for longer examples and explanations

I use an array to draw all GUI elements without hassle if I add / remove elements

((ArrayButton)elements[6]).selection worked anyways

Casting is the wrong solution here.

Show us the code with ‘public UIElement elements[] =’ in it. At a guess, you probably want some kind of UI object that holds a List that handles updating and drawing, and elsewhere you want to hang on to a specific Button instance that you then ask for information from.

Also consider making your class variables private and not having everything public.

Why is it a wrong solution?

Because it’s fragile and prone to breaking (via a ClassCastException) if/when you change the button into something else.

You’re also duplicating information (you’re saying that element[6] is a Button both when you’re creating it and when you access it). Google ‘don’t repeat yourself’.

It’s also completely unnessesary with just a small restructuring.

I’m not going to join the debate on casting or not casting, but did you actually type the < and > as part of your variable name? Because that definitely won’t work if your variable is just named selection. Try removing those.