Reputation: 248
I'm working through a Java polymorphism exercise and struggling to understand type conversion & how to call subclass-specific methods. I have a class Dog:
public class Dog
{
private final String breed;
public Dog(String b)
{
breed = b;
}
//More Dog methods (bark, eat, etc.)
}
as well as a subclass SledDog, who can pull a sled:
public class SledDog extends Dog
{
public SledDog(String b)
{
super(b);
}
public void pullSled()
{
System.out.println("pulling the sled");
}
}
In my application, I declare 3 dogs - two regular Dogs and one SledDog. I pass them into an array of Dogs, and I loop through that array. If the dog is a sled dog, I want him to pullSled() - but I can't figure out how to call the method, since it belongs to a subclass. My instructions tell me to cast the array item into a SledDog object, but I can't figure out how, or why it is necessary. I thought that since the object passed to array is already a SledDog, it should have access to pullSled(). Here's my attempt.
public class DogApp
{
public static void main(String[] args)
{
Dog firstDog = new Dog("Greyhound");
Dog secondDog = new Dog("Terrier");
SledDog sledDog = new SledDog("Husky");
Dog[] dogArray = new Dog[]{firstDog, secondDog, sledDog};
for(Dog d : dogArray)
{
//Makes sense, only want to pullSled() if d is a SledDog
if(d instanceof SledDog)
{
// This is the part I'm confused about
d = (SledDog) d;
d.pullSled();
}
}
}
}
Upvotes: 0
Views: 660
Reputation: 3831
If you need a real polymorhic case you can use
superclassName referenceName=subclassObject
in this way you can access all methods of subclass by use of superclass reference.
Just a hint to get you started,try and take it further good luck!
Upvotes: 1
Reputation: 76918
When talking about OOP, trying to discern what the concrete subclass actually is generally means you're doing something wrong.
You could approach this issue by defining a default pullSled()
in your Dog
class, then overriding it:
public class Dog
{
private final String breed;
public Dog(String b)
{
breed = b;
}
public boolean pullSled()
{
System.out.println("Dude, I'm a " + breed + ", not a Siberian Husky!");
return false;
}
//More Dog methods (bark, eat, etc.)
}
public class SledDog extends Dog
{
public SledDog(String b)
{
super(b);
}
@Override
public boolean pullSled()
{
System.out.println("pulling the sled");
return true;
}
}
Another option over this simple example, you could also define a field and boolean canPullSled()
:
public class Dog
{
private final String breed;
protected boolean canPullSled;
public Dog(String b)
{
breed = b;
}
public boolean canPullSled()
{
return canPullSled;
}
public boolean pullSled()
{
if (canPullSled)
{
System.out.println("pulling the sled");
return true;
}
else
{
System.out.println("Dude, I'm a " + breed + ", not a Siberian Husky!");
return false;
}
}
// other stuff
}
public class SledDog extends Dog
{
public SledDog(String b)
{
super(b);
this.canPullSled = true;
}
}
Or use a Builder ... or a fluent interface ... or ...
In the end, instanceof
is really a last resort, used only when nothing else will do.
Upvotes: 2
Reputation: 7057
There is difference between an object and a reference to an object.
All SledDogs are Dogs but all Dogs are not SledDogs. So according to this logic (as far as compiler understands), following code is fine.
Dog myDog = new SledDog(); // This compiles
while
SledDog myDog = new Dog(); // Error
does not work.
So in the first line, the tricky part is that you have an object of SledDog
class but you are referring to it by a reference of Dog
class. (Since all SledDogs are Dogs, this is perfectly fine)
But while doing this, you are ignoring it's SledDog
ness. You will be able to access features of SledDog that are inherited from Dog
, but SledDog specific features will be unavailable. Remember that object is still a SledDog but you are acknowledging it as a mere Dog
.
So in order to access them, you'll have to refer it using a reference of SledDog
class. ---> Hence the typecast is required.
SledDog typeCastedMyDog = (SledDog) myDog;
Now you can access the pullSled() method.
The same logic applies when you put all of them in an array of Dogs.
Hope this helps.
Upvotes: 2
Reputation: 34186
You are pretty close, just cast it and call the method:
((SledDog)d).pullSled();
inside the if (d instance of SledDog)
condition.
Also, I can't see the declaration of dogArray
. Be sure you have declared and initialized it correctly.
Upvotes: 2