Sunday 16 June 2013

Why Students are not Persons and also Employees are not Persons either !! Well lets see whats goin on....

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.

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