Reputation: 783
I have an abstract Person
class which has 3 children: Admin
, Employee
and Student
. There is only one admin object.
I also have a class which it's "name" is Statics
and holds all public data I need, like this:
public class Statics {
private static Person currentLoginUser;
private static ArrayList<Person> people = new ArrayList<>();
private static ArrayList<Student> students = new ArrayList<>();
private static ArrayList<Employee> employees = new ArrayList<>();
//We don't need ArrayList<Admin> because there is only one admin in the whole program
//Adder and getter methods:
//...
}
You may ask what ArrayList<Person>
in the code is? When I create an object, I add it to both "it's own type arraylist" and "ArrayList<Person>
". So ArrayList<Person>
has everybody.
As I said, I only have 1 admin:
Person admin = new Admin(); //`Admin` extends `Person`
I want to create a method (in Admin
class) which takes an arrayList of Person
as input and prints it's data. So I did this:
//Admin class:
public void printList(ArrayList<Person> people){
//Do something
}
Let's assume admin
wants to see the list of the students: I call it like this:
ArrayList<Student> s = Statics.getStudents();
((Admin)admin).printList(s); //admin object was created by `Person` class so I have to cast it to (Admin) to use `Admin`'s own methods.
It (eclipse) says that:
The method printList(ArrayList<
Person
>) in the type Admin is not applicable for the arguments (ArrayList<Student
>)
I tried to cast it to person:
((Admin)admin).printList((ArrayList<Person>)s);
this time I got this error:
Cannot cast from ArrayList<
Student
> to ArrayList<Person
>
In this link the answer is to pass the main arrayList and check if it's object's are from type "Student" or not, then print it's value but I don't want to check the whole Person
arrayList everytime! I just want a method, which takes and arrayList of Person
's children (Employee
, Student
, etc) and prints them.
Upvotes: 0
Views: 382
Reputation: 592
As mentioned by @Abra problem is with generics. You can use generics in your code to fix your problem.
Create Admin
class as a generic class and create printList
method with
List<T> list
argument so that it will accept any type of object. e.g Person, Employee, Student etc.
This is just an example so please change your code accordingly.
public class Admin<T> {
public void printList(List<T> list) {
// Print list here
}
}
Statics stat = new Statics();
Admin admin = new Admin<Student>();
// Students
admin.printList(stat.getStudents());
// Employees
admin.printList(stat.getEmployees());
// People
admin.printList(stat.getPeople());
Upvotes: 1
Reputation: 8307
Change printList
method signature to:
public void printList(ArrayList<? extends Person> people)
Explanation:
Changing the signature will allow you to pass an ArrayList
parameterized with Person
or its subclasses.
In java the ? extends T
construct is known as Upper Bounded Wildcards.
When using the people
inside the printList
method you will be able to "consume" (get
) people from the list (but not to "produce" (add
) them). "Consume" and "produce" are meant here in the PECS sense.
For more information about generics see Generics (Java tutorial)
Upvotes: 1
Reputation: 20924
Your problem is with generics. Even though Student
extends Person
, List<Student>
does not extend List<Person>
. That's why java generics has the wildcard which is represented with a ?
(question mark).
If you use List<? extends Person>
that means that each element in the list is an instance of either Person
or any class that extends Person
.
Refer to Generics, Inheritance, and Subtypes in the Generics lesson of the Learning the Java Language trail in Oracle's java tutorials.
Upvotes: 2