Reputation: 9
I am trying to use the Methods from a class that i have in an Array list.
The ArrayList is ArrayList With Appliance being a super Class.
the ArrayList contans objects that extends Appliance such as a Clock and Lamp.
when i use
arrayList.get(x) to grab the object at that point i cant see the methods that the object has, I can only see the superClass Objects.
Please can someone help me.
Thank you for reading
Code (Some of it)
public abstract class Appliance implements Serializable {
protected boolean power;
protected ImageIcon picture;
public Appliance() {
}
public void setPower(boolean power) {
this.power = power;
}
public boolean getPower() {
return power;
}
abstract ImageIcon getPicture();
@Override
public String toString() {
String powerVal;
if (this.power == true) {
powerVal = "ON";
} else {
powerVal = "OFF";
}
return "Power: " + powerVal;
}
}
public class Clock extends Appliance {
private int hours;
private int minutes;
private int seconds;
public Clock() {
super();
this.power = false;
this.picture = new ImageIcon("src/res/clock.jpg");
this.hours = 23;
this.minutes = 59;
this.seconds = 59;
}
public Clock(boolean pow, int hours, int minutes, int seconds) {
super();
this.power = pow;
this.picture = new ImageIcon("src/res/clock.jpg");
this.hours = hours;
this.minutes = minutes;
this.seconds = seconds;
}
public int getHour() {
return this.hours;
}
public void setHours(int hours) {
this.hours = hours;
}
public int getMinutes() {
return this.minutes;
}
public void setMinutes(int minutes) {
this.minutes = minutes;
}
public int getSeconds() {
return this.seconds;
}
public void setSeconds(int seconds) {
this.seconds = seconds;
}
@Override
public ImageIcon getPicture() {
return this.picture;
}
@Override
public String toString(){
return super.toString() + String.format(" and the time is %d:%d:%d",this.hours, this.minutes, this.seconds);
}
}
public class Lamp extends Appliance{
//Default constructor or Empty argument constructor
public Lamp(){
super();
this.power = false;
this.picture = new ImageIcon("src/res/lamp.jpg");
}
public Lamp(boolean pow){
super();
this.power = pow;
this.picture = new ImageIcon("src/res/lamp.jpg");
}
@Override
ImageIcon getPicture() {
return picture;
}
@Override
public String toString(){
return super.toString();
}
}
public class Controller {
private ArrayList<Appliance> myAppliances = new ArrayList<>();
private JLabel[] labelArray;
...................................................
@Override
public void mouseClicked(MouseEvent me) {
String[] options = new String[]{"yes","no"};
if (me.getButton() == 1){
try{
int x = Integer.parseInt( me.getComponent().getName());
Appliance myApp = this.myAppliances.get(x);
if(myApp.getClass().equals(Clock.class)){
JOptionPane.showOptionDialog(null, "Clock Info: /nTime: " + myApp., "Clock", JOptionPane.YES_NO_OPTION, JOptionPane.QUESTION_MESSAGE, null,options,options[1] );
}
} catch (Exception e){
System.out.println("Null Poiter");
}
}
}
}
Its the myApp. part in the clicked method
Upvotes: 0
Views: 118
Reputation: 1803
That's the expected behavior. It's how polymorphism works.
Let's take a look at an example using your own classes. Imagine holding a bag. You know that only Appliance
objects can go into this bag, so you go around all the appliances in your house into this bag - your Lamp
, your Clock
, maybe your Toaster
and a Blender
, and a bunch of others.
Now imagine you put on a blindfold and randomly pull out one of the appliances. Without looking at it, how can you tell what appliance it is? You can't! If you assume the thing you just pulled out was a Toaster
and you tried to toast()
your bread with it, what would happen if you were actually holding a Blender
? You'd get a bloody mess, probably. Therefore, the only thing you know for a fact that all Appliance
objects can do is turnOn()
or turnOff()
, so those are the only methods available to you.
In this example, you are the compiler and the bag is the list. If you tell the compiler that the list can hold only Appliance
objects, it will not assume anything else about the objects in the list unless you explicitly tell it to (for example, if you downcast the Appliance
object to a Toaster
by doing something like ((Toaster)applianceList.get(0)).toast()
).
Upvotes: 0
Reputation: 2989
ArrayList<Appliance> mylist = new ArrayList();
for(Appliance app : mylist){
boolean isAclock = app instanceof Clock;
boolean isALamp = app instanceof Lame;
if(isAlamp){
Lamp l = (Lamp)app;
}else{
Clock c = (Clock)app;
}
}
making your arralist to accept appliacnces will accept its sub classes bt the problem is receving the correct class object . you can use instance of and check the object type and then cast the object to its original type try using this approach
Upvotes: 0
Reputation:
It sounds like you're writing
List<Appliance> appliances = new ArrayList<>();
appliances.add(new Lamp());
appliances.add(new Clock());
Appliance appliance = appliances.get(0);
appliance.setAlarm(TOMORROW);
I think from this example you can see why you can't access the subclass methods. When you have a list of Appliance, you don't know if the objects in it are Clocks or Lamps, so when you get one out you can't call the subclass methods.
If you are positive the object is a clock, you could cast it:
Clock clock = (Clock) appliances.get(1);
clock.setAlarm(TOMORROW);
But this is not the Java Way. Typically you would use only superclass methods on Appliance, or maintain a separate list for Clocks and Lamps.
Upvotes: 0
Reputation: 3286
I assume you are doing something like this (sorry but it is not clear from your question):
ArrayList<SuperClass> al;
...populated with instances of Appliance
al.get(1).getClock(); //Compile error.
The problem is that java does not know if your element at that position is a SuperClass, Appliance, or something else that inherits from SuperClass. You can cast the code, to make it behave the way you want:
((Appliance)al.get(1)).getClock();
You may also want to use the instanceOf
operator to make sure you do have an instance of the class you are expecting.
Upvotes: 2