Reputation: 1202
I'm trying to make a little lwjgl GUI library by myself. I started again for 3 times now. My problem is that I fail to create a good OOP design. I looked at the Java built in library Swing and AWT. I dit read the codes, and studied the class design of Swing and AWT. But I think this is not the correct way to make my own GUI library for lwjgl, because it's something with much differences. One of my biggest problems I Always have in OO is that I can't reach a method. I think this is a general programming problem. For example, I have the following classes:
class Container {
private ArrayList<Component> components = new ArrayList<Component>();
public void add(Component c) { // Accepts only Component objects, or child objects of Component
this.components.add(c);
}
public volid paintAll() {
for(int i = 0; i < this.components.size(); i++) {
// Not possible, the Component object has no method paintComponent(), the
// class which extends Component does. This can be a button, but it's stored as
// a Component. So the method paintComponent "Does not exist" in this object,
// but is does.
this.components.get(i).paintComponent(); // error
}
}
}
class Component {
private int x;
private int y;
private int width;
private int height;
/* methods of Component class */
}
class Button extends Component {
private String text;
public Button(String text) {
this.text = text;
}
public void paintComponent() {
/* Paint the button */
}
}
// In Swing, the Component class has no method like paintComponent.
// The container can only reach the methods of Component, and can not use methods of
// classes which extends Component.
// That's my problem. How can I solve this?
Container container = new Container();
Button b = new Button("This is a button");
Container.add(b); // b "Is a" Component.
Upvotes: 2
Views: 1811
Reputation: 15547
If you need to store your buttons as components, you can use the instanceof
operator to check if they are actually buttons and then call any methods that only buttons have by casting them like this:
for(int i = 0; i < this.components.size(); i++) {
if(components.get(i) instanceof Button){
Button b = (Button)components.get(i);
b.paintComponent(); //or any other methods that buttons have.
}
//treat it as a normal component;
}
Alternatively you could store your buttons seperately from your components which are not buttons and then not need to cast them.
Upvotes: 1
Reputation: 182048
You need to make sure that every subclass of Component
has a paintComponent()
method. You can do that by declaring it as abstract in the superclass:
abstract class Component {
/* fields of Component class */
public abstract void paintComponent();
}
This will force every non-abstract subclass of Component
to implement the method, otherwise the compiler will produce an error.
Swing does the same thing: JComponent
has a method paint(Graphics)
.
Aside: because Component
is already present in the name of the class, it would be more customary to name the method paint()
instead. This avoids repetition in the call, e.g. myComponent.paint()
instead of myComponent.paintComponent()
.
Upvotes: 2