Consider the following structure :
Employee -------- > Person <--------- Student
Both Employee and Student extends Person.
(Note that arrow is always towards the Parent class and tail towards the subclasses)
Now
Each Student is a Person.
Each Employee is a Person.
So
Person somePerson = new Student(); // perfect no probs!!
Person someOtherperson = new Employee(); // perfect no probs either!!
Also
Student student = new Student ();
Employee emp = new Employee();
Person p = student ; // perfect
p = emp; // perfect
So Basically if a Child extends or implements Parent , depending upon if Person is a class or an interface, below code do not pose any problems.
( Assuming Child is a concrete class with default public constructor )
Parent parent = new Child();
NOW Having said all that above lets have some more students and employees. ( Below <Type> any thing that goes inside <> is Generic type. If it goes with List<T> this means List is a collection of objects of type T, T may be Student, Employee etc. )
List<Student> students = new ArrayList<Student>();
List<Employee> employees = new ArrayList<Employee>();
so now a question :
List<Person> persons = students;
is perfect or is there some thing wrong. Going by the intuition and if above was well absorbed then answer should be yeah, this is just perfect. Isn't a group of students a group of Persons, they are.
OK now having agreed upon that lets see this.
OK now having agreed upon that lets see this.
No problems with
List<Person> persons = students;
=> persons and students both points to a single object which is a
List of students.
But hey, all employees are persons too,
persons.add(new Employee()); //this should be perfect too.
Whats wrong with that. !!
Okkss are we adding an Employee to a List of Students.
Hmmm.... no we don't want that. Students are students Employees are Employees, though both are Persons.
Hence. from above :
List<Student> students = new ArrayList<Student>();
List<Employee> employees = new ArrayList<Employee>();
so now a question :
List<Person> persons = students;
this is NOT OK!!. This can lead to addition of Employees to students.
______________________________ ______________________________ ______
So whats the catch :
Basically when it is said :
Student s = new Student();
Person p = s;
There is only one object to which both p and s points to.
Now if We say
Employee e = new Employee();
and
p = e;
Now p no more points to Student object , now both e and p points to Employee Object and s points to Student alone. So no HARM.
But when we say
List <Student> students = new ArrayList<Student>();
List<Person> persons = students;
persons and students points to object of a list of Students but same time persons can have more persons being added to it like Employees so This leads to addition of Employees to the list of Students and hence COMPILER says this is not done .
Students derive from Persons but
List<Student> do not derive from List<Person>.
List<Person> persons = new ArrayList<Person>();
persons.add(new Employee());
persons.add(new Student());
this is ok but
persons = new ArrayList<Employee>() is NOT OK.
________________________________________________________________________________
few extra words:
OK now having the above understanding there are few more things to explore like the wild cards,etc. Also in java 7 we have few new features like
we can say
List<Student> students = new ArrayList<>(); // This is acceptable. On right hand side we can skip the type and simple <> shall suffice.
Also it is always a good idea to program to interfaces or super types for flexible design ( SuperType variable taking objects of Sub types as Person p = new Student(). and on left hand we have List and on right hand side we have ArrayList. This is a good design, Better read more on this!!)
Good Luck!!
Krishna