Reputation: 587
When i try to create an instance of a class and add this to my arraylist i can't call methods defined in the child.
How do i make this work?
List class:
import java.util.*;
public class List {
private ArrayList<Person> persons;
public List(){
persons = new ArrayList<Person>();
}
public void addAssistant(){
Person person = new Assistant();
persons.add(person);
if(person instanceof Assistant){
person.assist();
}
}
}
Person class:
public class Person {
public Person(){}
}
Assistant class:
public class Assistant extends Person {
public Assistant(){}
public void assist(){
System.out.println("I am assisting!");
}
}
Compiler: line: person.assist(); within the addAssistant() method in the List class.
Compiler error: The compiler cannot find symbol - method assist().
Upvotes: 2
Views: 3132
Reputation: 1858
I would code it this way
public void addAssistant(){
Assistant assistant = new Assistant();
assistant.add(person);
assistant.assist();
}
There is no point in abstracting yourself from the knowledge that your recently created object is in fact an Assistant.
Abstracting yourself from the concrete type is a good way of reduce coupling between two pieces of code and it is necessary for doing nice things like polymorphism... but in this particular example you are showing us you are already tightly coupled to an Assistant (in fact you are instantiating it just two lines above).
Another possible way to implement this is to use polymorphism, you can do that by adding the assist() method to the interface of your Person.
public class Person {
public Person(){}
public void assist() {
//I'm a just a person who doesn't assist anywhere
}
}
By doing so you are going to be able to do what you were trying:
public void addAssistant(){
Person person = new Assistant();
persons.add(person);
person.assist();
}
However I wouldn't recommend that, mostly because you will start filling your Person interface with responsibilities that are not correctly placed there. It's all matter of design, you need to choose the better (and of course, the most confortable) solution for your particular problem.
Good Luck Claudio
Upvotes: 1
Reputation: 30528
You have to cast your Person
into an Assistant
like this:
if(person instanceof Assistant){
((Assistant)person).assist();
}
This type of casting howerver is an indication of flawed application design I think.
Just a sidenote:
You should use interfaces instead of concrete implementations. So you should replace this:
private ArrayList<Person> persons;
with this:
private List<Person> persons;
If you want your Person
s to do their specific work and an Assistant
s work is assisting than you can work around this by creating an abstract method in Person
public abstract void doYourWork();
and you can implement that in Assistant
:
@Override
public void doYourWork(){
// doing something
}
In this case you don't have to explicitly cast your Person
objects.
If Person ain't going to have any concrete implementations you can make it an interface instead.
Upvotes: 1
Reputation: 26819
Person class does not have assist method defined so you must explicitly cast to Assistant class e.g.
if(person instanceof Assistant){
((Assistant)person).assist();
}
Upvotes: 1
Reputation: 8318
The way Java
language has been designed, this doesn't compile (as you've figured it out as well). Think of it this way, all assistants are persons, but not all persons are assistants. If you use an explicit cast, you can do what you want to achieve (as NPE mentioned in his answer).
Upvotes: 0
Reputation: 1197
You need to make a cast for use a subclass method
if(person instanceof Assistant){
((Assistant)person).assist();
}
Upvotes: 1
Reputation: 500257
You need an explicit cast:
if(person instanceof Assistant){
((Assistant)person).assist();
}
However, I think this type of logic should generally be discouraged.
Upvotes: 8