Interface-oriented programming ()
The previous sections are only the basis and foundation for this article, and they are very simple because they are easy to understand. Starting from this chapter, we use a lot of code to elaborate interface-oriented programming.
Interface Evolution
Now let's review the inheritance-related knowledge. We now provide a new set of inheritance systems. They are related to graphics. We can assume that we want to create a graphic Board (such as a Windows graphic Board), at least a few circles and rectangles must be drawn on it. Therefore, we naturally define the following classes.
Class
Shape // abstract in fact
{
Public
Virtual
Void
Draw ();
}
Class
Circle: Shape
{
Public
Override
Void
Draw ()
{
/*
Draw a circle on some device
*/
}
}
Class
Rect: Shape
{
Public
Override
Void
Draw ()
{
/*
Draw a rect on some device
*/
}
}
First of all, we cannot provide the Implementation of the draw () method of the Shape class. Because it is an abstract type (do not confuse it with the abstract class or abstract keyword in the language,
But they do have a great connection, but what I call abstraction is a real abstraction.) We do not know how a so-called "image" should be drawn. It's just like you let me draw a picture.
It is very difficult. I draw a circle or a polygon, or a pentagram. It seems that it is not an abstract image.
Let's review the polymorphism. The code below better explains the role of polymorphism.
Array
<
Shape
>
Shapes
=
{
New
Circle (),
New
Rect (),
New
Circle (),
New
Circle (),
New
Rect ()};
Void
Drawshapes ()
{
Foreach
(Shape
In
Shapes)
{
Shape. Draw ();
}
}
This is a pseudo code, but it naturally shows that in addition to polymorphism, foreach cyclically lists various derived class objects of the Shape class from the container. They all call their respective classes with polymorphism.
Type draw () method. This process does not clearly show the participation of a specific derived class type. Therefore, we can naturally generate a rounded rectangle or a pentagram.
Let them inherit from the shape class. They can also be naturally put into the shapes container without modifying the code in the loop. This is what we are pursuing for scalability and "New Code ".
The existing code is not affected ".
Well, it's all perfect, isn't it? However, is this perfect?
Is a table a shape (object? Is text a shape? If we want to have several layers, is each layer a shape? If so, do these elements appear on the graphic board interpret the belief of is-a well?
No, because a table is not a shape, text is not a shape, but they can also be painted on the top, so we need to perform an important evolution.
In the C ++ grammar textbook, we do not emphasize the interface concept, but use a pure abstract class to express this meaning. However, I prefer to use the Java interface keyword for expression. However, we must be clear that both interfaces, base classes, abstract base classes, and polymorphism exist in these syntactic relationships.
Interface
Idraw {
Void
Draw ();
}
Class
Circle
Implements
Idraw {
Void
Draw (){
/*
Draw a circle on some device
*/
}
}
Class
Rect
Implements
Idraw {
Void
Draw (){
/*
Draw a rect on some device
*/
}
}
This evolution does not seem to have essentially changed. Especially for C ++ compilers, the compiled code may not be any different. A lot of people may start to sigh and think that this kind of change doesn't matter at all, or even is a waste of time.
But what I want to say is that for design, this change is an essential change. Because the relationship between objects has changed, we previously mentioned that a circle object is also a shape that satisfies the is-a classic relationship, but now this relationship is broken.
Can-do & Constraint
We have mentioned the object relationship between has-a and is-a in the previous chapter. Now, we focus on the relationship between Can-do, this relationship indicates constraints ).
Therefore, in the above Code, we say that the circle class implements the idraw interface, or that the circle object can fulfill the behavior required by the idraw interface.
Void
Draw (idraw D)
{
D. Draw ();
}
This function intuitively expresses the concept of a constraint, "Draw an object that can be painted". To be precise, this function is more directly completed.
Constraint Semantic Expression of the idraw interface: only objects with constraints can be passed in and its draw () method can be called (note, instead of draw () method objects can be passed in and tuned
For more information, see C ++ 09 concept ).
Array
<
Idraw
>
Drawlist
=
{
New
Circle (),
New
Rect (),
New
Circle (),
New
Table (),
New
Rect (),
New
Textarea ()};
Void
Draw ()
{
Foreach
(Idraw d
In
Drawlist)
{
D. Draw ();
}
}
I use this pseudo code to clearly express a new situation where circle is drawn to the canvas, and table and textarea can also be painted.
There are still doubts. Is there a problem if table is derived from shape? Do you have to create an idraw file to make it look reasonable?
No. First, if the idraw interface does not replace the shape class, we also need to acknowledge that the shape class still carries the meaning of the idraw interface, although we do not abstract it.
In addition, there is no right or wrong design. It is the most practical criterion to determine whether to adapt to requirements. Our current example is quite simple. We only involve drawing elements, but there may be other problems.
(There are always many new requirements), such as alpha mixing, layer occlusion, element selection, ant line rendering, and so on. For example, when we select a rect, there is an ant line around it, and
When we select a textaread, it is surrounded by a border with eight adjustment points. However, we do not intend to involve the ant line and border in the occlusion calculation and Alpha hybrid Calculation of other elements.
And they are not involved in serialization. Therefore, they are neither shapes nor idraw interfaces. Experience tells us that the shape class is not enough to become the base class of all elements.
The idraw interface is not omnipotent. The specific solution depends on the requirements and how to cope with these needs.