Questions about "casting operation" in OOP
When programming, we usually use some type-casting operations.
When the casting happens on the objects "on the same level", it feels ok. But when it happens on the ojects "on the different levels"(mainly between father and son), it feels weird.
Considering this:
Class Son extends Father
WhenSon s = (Son)father;
, it's absolutely unreasonable. Because a "Son" is not a "Father" anymore, "Son" may grow up with some new properties "Father" doesn't have, the casting operation makes these properties unknown.
On the other hand, Father f = (Father)son
seems reasonable, but according to LSP
"An instance of a derived开发者_JAVA百科 should be able to replace any instance of its superclass"
A "Son" can do anything his "Father" can, so the casting operation seems useless.
So can i say that these casting operations are agaisnt OO design principle but necessary?
Casting objects in OOP is usually the product of either class inheritance or interface inheritance. One has to always remember that class inheritance denotes an "is a" relationship, and interface inheritance denotes a "has a" relationship.
Let's go over to your example: Class Son extends Father
doesn't sound like a reasonable abstraction, since every male person is a son, but not all of them will be a father. In fact, the opposite might be more applicable: Class Father extends Son
because every father is always someone's son.
On the other hand, we could just ditch this whole abstraction and say that we have, instead, a Class Person
that can either be a male or a female, a mother or a father, and so on. Each person will have an attribute containing collection of Person
with name Children
.
In this abstraction, a Person
will only be considered a Father
if its gender is male and if Person.Children.Count > 0
. This is much simpler than defining a Father
class in and by itself.
I find questions like these always interesting and it lends itself to some kind of debate I think :)
Here are my thoughts. In class design I would in this case create a class of Person
class Person
{
public bool IsFather { get; set; } // this variable will change depending on the count of children
public List<Person> children { get; set; }
}
When I create a derived class, the class should be a specialized person and in the case of Father and Son, I wouldn't create a Father class and a Son class.
You've got a bad example of inheritance.
A better one could be
Class Person
{
public void walk();
}
Class Man extends Person
{
public void shaveBeard();
}
Inheritance is the way to represent an is a relationship; e.g. "a Man
is a Person
".
Using the Objects
Either of these lines is OK.
Person p = new Person();
Person m = new Man();
It is fine to call p.walk
on both. However to call the shavebeard()
method, m
has to be a Man
object. For reasons of type safety, you have to cast it to a Man
object; e.g. (Man) m.shaveBeard();
The cast here will fail, so it's best to check that the variable refers to an instance of Man
:
if(m instanceof Man)
{
(Man) m.shaveBeard();
}
Neither seem reasonable to me. What seems more plausible:
Son s = (Son)person //Valid
Father f = (Father)person //Valid
Here's a hint: the Class on the left hand side is the superclass and that on the right side is the subclass so if we have this: Object p = new Student(); //is correct Student s = new Object() //is wrong...it's like saying that every Object is a student.. Care must be considered when doing explicit casting as it may look correct but might not work as expected. You can't instantiate your father's private property to yourself.
精彩评论