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
Nice piece of information. Keep it up!!
ReplyDeleteThis comment has been removed by the author.
ReplyDelete?
DeleteI have a doubt :O
ReplyDeleteis it valid if student extends both employee and person classes??????
@Khushi, First of all thanks for the comment,
DeleteKhushi is a nice name and seems I got a topic for my next non technical blog. The name means happiness. :)
Also the question asked inspire me to write another blog over multiple parent classes for a child class:
But in short I shall try to answer the question.
The simple answer you can find is the Diamond problem but apart from that there s little more than the diamond problem. I ll try to make u understand in short here .
Suppose There is a class Food having an abstract method
public abstract String getTaste(),
Now there are two non ABSTRACT concrete classes :
SaltedFood extends Food
giving implementation to getTaste() and returning "Salted".
And
SweetFood extends Food
giving implementation to getTaste() and returning "Sweet"
Now Suppose There is another Imaginary NON ABSTRACT CONCRETE class :
Lets suppose KhushiPreparedCurry extends SweetFood and also extends SaltedFood.
Now KhushiPreparedCurry has getTaste() from its parent classes and also lets suppose the developer did not decide to give its own implementation of getTaste() and use the concrete implementation of the parent classes.
Now on creating the objects of KhushiPreparedCurry and calling the method getTaste() using
khushiPreparedCurry Object.getTaste();
What shoud be returned Sweet or Salted.?
Now This is the diamond problem.
so MULTIPLE INHERITANCE IS NOT ALLOWED IN JAVA.
But then you can say a class inherits from two classes how :
GrandMa<---Ma<---Child now Child inherits Ma and GrandMa....
Also There are interfaces, A class can implement multiple interfaces. Now just give a thought if two interfaces have same method signatures, and also if two interfaces have same
method name, same parameters but different return types and a class implements both of them, how will be the implementation be affected ...leaving you on this thought, shall be back with more blogs...take care..God bless..
well i knw the answer to this... if a class implements 2 or more interfaces having same ABSTRACT method, this only forces the child class to define this method so thr is no prob with it since class has its own SINGLE definition to the ABSTRACT function :), though if the interfaces have abstract VARIABLE of same name then we have to use the variable though Class Name of Interface... :)
ReplyDeleteand if thr is a condition like person<-Student<-Employee
then
List students = new ArrayList();
List persons = students;
then
list.add(new Employee());
will be valid???? as in this case now every employee is also student, every student is also person.
so in this case what will java interpret :O
PS: Nice Blog...Awesome Explanation. Have a Nice Day
Good words and praises !! who doesn't like them...I like them a lot thanks:)
DeleteNow in reply I got two points to say :
Point number 1 :
Few terms :
Class, Interface, methods, properties, abstract.
So @Khushi lets replace function with method and variable with property in your comment above.
Abstract is an adjective used for methods and classes. Any class having a method which is abstract is an abstract class.
Meaning of abstract by google : Existing in thought or as an idea but not having a physical or concrete existence.
Now all interfaces are abstract and their object can not be instantiated.
All methods in an interface are abstract.
What about the properties.
ALL PROPERTIES OF AN INTERFACE ARE PUBLIC STATIC FINAL.
(and you said variable, to which I ll say BBT bazinga!! heh:P , sorry for this but I loved BBT whatever little I have watched)
Also as we have the properties as final so we have proper object or if primitive type we have a known final value of the same, so abstract for the properties we do not use.
Point Number 2 :
person<---Student<---Employee
in this case
List students = new ArrayList();
List persons = students;
Both students and persons are general List and not the list of Student or Person Or Employee, You can add object of any java concrete class in it,, why just Employee.
Raw List : List students = new ArrayList();
List of student : List < Student > students = new ArryList < Student > ()
The second type of list was introduced in java 5. This helps in type checks at run time.
But in case we would have had
List < Student > students = new ArrayList < Student > ();
List < Person > persons = students; // this line shall give you compilation error.
As I have said in the blog :
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.
hmm..we may miss few things while first time reading something, I would recommend my blog once again and completely.
Keep smiling ..:) God Bless..
in Comment above we have three concrete classes
DeleteEmployee -------- > Person <--------- Student
was very confused somewhere then i implemented it myself to see results Now m kind of happy... sometimes u need to discuss in deep to remember it for life time...:)
ReplyDeletePS. its a great blog plz write more
@Khushi : thanks for reading and appreciating my first writing. Nice to know you implemented the idea yourself and saw the result.
ReplyDeleteNow I hope you would understand why I choose the topic as :
Why Students are not Persons and also Employees are not Persons either !! Well lets see whats goin on....
Its very important to implement once you read bout an idea so that you can understand what the idea is all about in reality.