[Learning little bit-object-oriented] the dilemma of object-oriented-a square cannot inherit a rectangle?

Source: Internet
Author: User
The dilemma of object-oriented methods -- a square cannot inherit from a rectangle?

Http://blog.csdn.net/javayuan/article/details/1191751 ()

At the beginning of object-oriented theory, inheritance abuse is often caused by lack of guidance from best practices. A famous example is that the Stack class Stack in the Java class library inherits the Vector class.

Public class Stack extends vector ...{
Public object push (Object item )...{
Addelement (item );
Return item;
}
Public synchronized object POP ()...{
//...
}
}

Just to reuse the management Element Method of vector, stack inherits from vector, resulting in a poor design. People come up with a rule: Combination rather than inheritance is preferred. inheritance is used only when class A is "is a" Class B. Stack is not a vector, so a combination should be used in this case. The sample code is as follows:

Public class Stack ...{
Private vector;
Public object push (Object item )...{
Vector. addelement (item );
Return item;
}
//...
}

Inheritance can be used only when it conforms to the "is a" relationship. This rule is consistent with our intuition. Object-oriented technology is to use the objects in the software to simulate objects in reality. If a dog is not a cat, it cannot be inherited from a cat. However, in actual software development, it is quickly discovered that in some cases, even if Class A does "is a" Class B, inheritance cannot be used. One of the most famous examples is that a square cannot be inherited from a rectangle. Many books about object-oriented design have them. This is an intuitive example. The sample code is as follows:

Public class rectangle ...{
Private double width;
Private double height;

Public rectangle (double width, double height )...{
This. width = width; this. Height = height;
}
Public double getheight ()...{
Return height;
}
Public void setheight (double height )...{
This. Height = height;
}
Public double getwidth ()...{
Return width;
}
Public void setwidth (double width )...{
This. width = width;
}
//...
}
Public class square extends rectangle ...{
Public void setheight (double height )...{
Super. setheight (height );
Super. setwidth (height );
}
Public void setwidth (double width )...{
Super. setheight (width );
Super. setwidth (width );
}
//...
}

The setheight and setwidth methods in the rectangle class are not suitable for the square class. To ensure the square length and width are equal, the two methods are rewritten. The above code looks reasonable at the beginning, but there is actually a problem. I will not discuss the defects of this Code in detail. Many books have made a detailed analysis on it. I just pointed out its unreasonable points in theory. Based on contractual design, there are the following principles:

The preconditions of the subclass cannot be stronger than those of the parent class.
The post condition of the subclass cannot be weaker than the post condition of the parent class.
The non-variant class of the subclass cannot be weaker than the class non-variant of the parent class.

This principle can also be derived from the liskov replacement principle. For example, to replace a parent class with a subclass, any parameter accepted by the parent class must be accepted by the subclass. That is, the precondition of the subclass cannot be stronger than that of the parent class.

For the setheight method of the rectangle class, the precondition is height> 0, and the Post condition is this. Height = height & this. width = old. width. For the setheight method of the square class, the precondition is also height> 0, which is not stronger than the precondition of the parent class. However, the post condition becomes this. Height = height & this. width = height. It violates the post-condition of the parent class. The postcondition of the subclass cannot be weaker than the postcondition of the parent class, which means that the subclass must comply with the postcondition of the parent class and add its own stronger postcondition.

People have put forward the concept of subtypes in this abnormal situation. In the above Code, the square class is a subclass of the rectangle class (subclass), but not a subtype ). Because it violates the liskov replacement principle. The introduction of this concept should be said to be confusing.

So why is this abnormal? The square is a rectangle, and it is reasonable to use inheritance. If there are too many exceptions in a design method, it is certainly not a good design method.

INSTRUCTOR: Please check it out! This is a square. Now I want to increase its vertical edge height. What shape is it now?
Student: The report teacher is a rectangle.
Teacher: the answer is correct.

We can see that the side length of a square can be changed independently in reality, and the changed shape is no longer a square. We were inspired by the comparison with the actual situation. That is, the square and rectangle should be immutable classes. When its side length changes, it becomes a new rectangle.

Public class rectangle ...{

Private double width;
Private double height;

Public rectangle (double width, double height )...{
This. width = width; this. Height = height;
}

Public double getheight ()...{
Return height;
}
Public double getwidth ()...{
Return width;
}


Public rectangle changeheight (double height )...{
Return new rectangle (this. width, height );
}

Public rectangle changewidth (double width )...{
Return new rectangle (width, this. Height );
}
}


Public class square extends rectangle ...{
Public Square (double dege )...{
Super (dege, dege );
}

Public Square changeedge (double edge )...{
Return New Square (edge );
}
}

Through this idea, we have obtained a design that is completely consistent with the actual object. Therefore, it is not a square that cannot inherit from a rectangle.

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.