Nature of software design-vernacular object-oriented ZZ
Different people refer to different meanings when talking about Object-Oriented Programming (OOP.
Some people think that any application using graphical interfacesProgramAll are object-oriented.
Someone uses it as a term to describe a special inter-process communication mechanism. Some people use this word in a deep sense. They actually want to say, "Come on, buy my product !" I generally do not mention Oop, but as long as it is mentioned, I mean using inheritance and dynamic binding programming methods. -- "C ++ meditation"
"C ++ meditation" is about a dozen years ago. Now, the answer to object-oriented is a public phrase: encapsulation, inheritance, and polymorphism. As we all know, in object orientation, a car is an object, and the concept of a car is a class. The car has a beautiful appearance, hiding all kinds of Internal principles, and the driver does not have to know its internal working principles to drive, even if the car continues to upgrade with technological advances, there is no impact on drivers, which is the advantage of encapsulation.
Automobiles are a type of transportation tools. automobiles are a type of transportation tools, and transportation tools include automobiles, which have more extensive significance. This abstract-to-specific relationship is the inheritance relationship. We can say that the automobile class inherits the Transportation Tool class, the automobile class is the subclass of the Transportation Tool class, and the Transportation Tool class is the parent class of the automobile class.
As a means of transportation, it can certainly be moved, from the first place to the second place, it has played a role in transportation. Ships are a type of transportation, so ships are also a subclass of transportation tools. In the same way, the movements of ships are definitely different from those of cars. In this way, completing the same function in different ways is called polymorphism.
Object: an object is a specific thing, such as an apple. A computer is an object. Each object is unique. Two apples, no matter how similar they look, have similar internal components. After all, two apples are two different objects. An object can be a physical object or a concept. For example, an apple object is a physical object, and a policy may be a conceptual object.
Class: an object may be an infinite set. It is unrealistic to use enumeration to represent an object set. Abstract The features and functions of objects and classify objects according to this standard. This introduces the concept of classes. A class is a general term for a class of things. A class is actually a classification standard. All objects that comply with this classification standard belong to this class. Of course, for convenience, we usually only need to extract the features and functions that are useful to the current application.
Abstract class: A class is an abstraction of objects. For example, Apple is an abstraction of all specific apples. If we abstract the apple class step by step, we can get a fruit class. This class is abstract. Unlike ordinary classes, an abstract class has no corresponding objects. Like apple, you can always get something called Apple. For fruit, there is nothing really called fruit. You can say that an apple is a fruit. Logically, there is no error, but it makes no sense. Abstract classes cannot be instantiated in programs.
About object-oriented: Object-oriented is object-centric. Why not face classes, but objects? Classes are a collection of objects. Classes are actually considering objects, and sometimes they are not strictly distinguished. Therefore, the word object-oriented is more accurate than the class-oriented one.
Since the object is the center, the content taken into consideration by the object is naturally the object, the collaboration between objects, the classification of objects, and the relationship between classes, which leads to several important concepts.
1. Encapsulation
What: objects also have privacy. Object privacy is the Implementation Details of objects. To maintain a good image of an object, we need to protect the object's privacy. The so-called encapsulation is actually to protect the object's privacy. Of course, no one can completely hide their privacy. For example, when you transfer an account, you have to disclose your family information and health status. In addition, the number of private information disclosed on different occasions varies. Friends and family may know more about your privacy, followed by colleagues, and others may know less about it. Object-Oriented systems also consider these actual situations. Therefore, languages such as C ++ have keywords such as public, private, protected, and friend to adapt to different situations.
Why: encapsulation can isolate changes. Based on past experience, we know that internal implementation is easy to change. For example, the computer is constantly upgrading and the chassis is still square, but the CPU and memory installed in it are far from the past. The change is inevitable, but the scope of the change can be controlled. No matter how the CPU is changed, it should not affect the way users use it. Encapsulation is a good way to isolate changes. The CPU and memory are encapsulated in the chassis, and only some standard interfaces are provided for external use, such as USB ports, network cable ports, and display ports, as long as these interfaces remain unchanged, internal changes do not affect the user's usage.
Encapsulation can improve ease of use. After encapsulation, only the least information is exposed to the user. The external interface is clear, easier to use, and more user-friendly. Imagine how terrible it would be if common users wanted to know all kinds of chips and jumpers inside the chassis. So far, I still don't even know the hard drive jumper settings. Fortunately, I don't have to know.
How: in C language, you can use the structure + function to simulate the implementation of classes. The variable defined with this structure is an object. Encapsulation has two meanings. One is to hide internal behaviors, that is, to hide internal functions. Callers can only see public functions provided externally. The second is to hide internal information, that is, to hide internal data members. We recommend that you do not disclose any data members to the outside. Even data members that need to be known to the outside can only be obtained through functions.
It is easy to hide internal functions in the C language: Do not put them in the header file. when defining the function in the C file, add the static keyword before it. Each class is placed in an independent file. In this way, the function scope can be limited to the current file. The current file only has the implementation of the class itself, that is, only the current class can see these functions, which achieves the purpose of hiding.
It is troublesome to hide data members in C. It does not provide keywords similar to public/protected/friend/private in C ++. Only some special methods can be used to simulate partial effects. There are two common methods.
The first is to use the special Syntax of C to declare the structure in the header file and define it in the C file. In this way, all the data information of the structure can be hidden. Because the outside world does not know the size of the memory occupied by the object, it is not possible to create the object of this class statically. Only the creation function provided by the class can be called to create the object. The disadvantage of this method is that it does not support inheritance because the child class does not have any information about the parent class. For example:
Header file:
Struct _ lrcpool; Typeef struct _ lrcpool; Lrcpool * lrc_pool_new (size_t unit_size, size_t n_prealloc_units ); Void * lrc_pool_alloc (lrcpool * thiz ); Void lrc_pool_free (lrcpool * thiz, void * P ); Void lrc_pool_destroy (lrcpool * thiz ); C file: Struct _ lrcpool { Size_t unit_size; Size_t n_prealloc_units; }; Lrcpool * lrc_pool_new (size_t unit_size, size_t n_prealloc_units) { Lrcpool * thiz = lrc_alloc (lrcpool, 1 ); If (thiz! = NULL) { Thiz-> unit_size = unit_size; Thiz-> n_prealloc_units = n_prealloc_units; } Return thiz; } |
The second is to put private data information in an opaque priv variable. Only class implementationCodeTo know the real definition of priv. For example:
Header file:
Struct _ lrcbuilder { Lrcbuilderbegin on_begin; Lrcbuilderonidtag on_id_tag; Lrcbuilderontimetag on_time_tag; Lrcbuilderonlrc on_lrc; Lrcbuilderend on_end; Lrcbuilderdestroy destroy; Char priv [1]; }; C file: Struct _ lrcdumpbuilder { File * FP; }; Typedef struct _ lrcdumpbuilder; Lrcbuilder * lrc_dump_builder_new (File * FP) { Lrcdumpbuilder * Data = NULL; Lrcbuilder * thiz = (lrcbuilder *) calloc (sizeof (lrcbuilder) + sizeof (lrcdumpbuilder), 1 ); If (thiz! = NULL) { Thiz-> on_begin = lrc_dump_builder_on_begin; Thiz-> on_id_tag = lrc_dump_builder_on_id_tag; Thiz-> on_time_tag = lrc_dump_builder_on_time_tag; Thiz-> on_lrc = lrc_dump_builder_on_lrc; Thiz-> on_end = lrc_dump_builder_on_end; Thiz-> destroy = lrc_dump_builder_destroy; Data = (lrcdumpbuilder *) thiz-> priv; Data-> fp = FP! = NULL? FP: stdout; } Return thiz; } |
2. Inheritance
What: inherited description is an abstract to a specific relationship. Specific things inherit the characteristics of abstract things. For example, the concept of fruit is more abstract than the concept of apple, and its meaning is more general, while the concept of apple is more specific, the significance is narrower. In the object-oriented method, we can say that the apple class inherits the fruit class. Inheritance refers to inheriting the features of the parent class. The nature of inheritance stems from the classification, and the fine classification inherits the features of the big classification.
Why: inherits the description of the abstract relationship to the specific relationship, so it can effectively use the abstract weapon to overcome the complexity of the software. Abstract is everywhere in implementation. Class is the abstraction of things. When it comes to Apple, you think of a kind of things like Apple, without the need to care about its size, color, and composition, apple is enough. It seems that the old man has learned the power of abstraction.
Inheritance not only utilizes the power of abstraction to reduce the complexity of the system, but also provides a method of reuse. Let's assume that we acknowledge the inheritance relationship of the following aspects: Apple inherits fruit and fruit inherits food. If we already know what food is and what fruit is, when we describe Apple, there is no need to repeat the concepts of food and fruit. This is reuse and reuse the understanding of the concepts of fruit and food.
How: it is very easy to implement inheritance in C language. You can use the structure to simulate it. This implementation is based on an obvious fact that the layout of the structure in the memory is consistent with the declaration of the structure. We know that when a program describes the features of a thing, it mainly describes the attribute features of the thing through data variables, such as color, weight, and volume, and uses functions to describe the behavior features of the thing, and sports, growth and fighting. The Inheritance Method in C language is as follows:
Struct _ gobject { Gtypeinstance g_type_instance; Volatile guint ref_count; Gdata * qdata; }; Struct _ gtkobject { Gobject parent_instance; Guint32 flags; }; Struct _ gtkwidget { Gtkobject parent_instance; Guint16 private_flags; Guint8 state; Guint8 saved_state; Gchar * Name; Gtkstyle * style; Gtkrequisition requisition; Gtkallocation allocation; Dkwindow * window; Gtkwidget * parent; }; |
Inheritance
Inheritance is widely used in the real world, and the same is true in programs. It can be said that it is over-used. Several years ago, some masters proposed that the combination instead of inheritance should be preferred. There are three main reasons: Multi-Level inheritance and multi-level inheritance are too complicated, and the conciseness of abstraction is lost. Second, parent classes and child classes share too much information, and their coupling is too tight. Third, the relationship between the parent class and the Child class is statically bound at compilation, making it difficult to achieve polymorphism at runtime.
Currently, it is generally advocated that only inherited interfaces are not inherited and implemented. code reuse is achieved through combination. This is emphasized in "design pattern", and is also done in the COM of Ms. Therefore, I basically only use interface inheritance and seldom encounter any problems. We recommend that you follow this principle.
3. Polymorphism
What: Although polymorphism itself indicates the meaning it represents, it still makes beginners feel somewhat mysterious. Polymorphism is a variety of ways to accomplish the same function. For example, taking animal movements for example, birds usually fly, fish usually swim, and land animals usually run, the same is motion, but the method is different. This is polymorphism. Many people reply to polymorphism that functions with the same name are allowed to exist. This answer clearly does not grasp the nature of polymorphism.
Why: the benefits of polymorphism may not be displayed in the animal movement example. Let's consider another example of polymorphism, USB flash drive. The technical content of the USB flash disk may not be very high. Many manufacturers are designing and producing it. That is to say, the USB flash disk has many different implementations. This is the polymorphism of the USB flash disk. U disk polymorphism is good for consumers. With more options, you can balance the price, quality, and appearance, and choose your favorite U disk. The premise of polymorphism is interface consistency. Otherwise, polymorphism causes much more trouble than it brings benefits. Regardless of the size, color, and quality of the USB flash drive, it must comply with the corresponding USB standard, which can be used on any computer with a USB interface.
How: polymorphism is usually implemented using function pointers in C language. function pointers define the prototype of a function, that is, descriptions of its parameters and return values, and the meaning of the function, different functions can have the same function prototype, such as the sorting function. The implementation of these functions is different, but the function prototype can be the same. Under different circumstances, let the function pointer to different function implementations, which achieves polymorphism. The following C language example:
Interface:
Struct _ lrcbuilder; Typedef struct _ lrcbuilder; Typedef lrc_result (* lrcbuilderbegin) (lrcbuilder * thiz, const char * buffer ); Typedef lrc_result (* lrcbuilderonidtag) (lrcbuilder * thiz, const char * Key, size_t key_length, Const char * value, size_t value_length ); Typedef lrc_result (* lrcbuilderontimetag) (lrcbuilder * thiz, size_t start_time ); Typedef lrc_result (* lrcbuilderonlrc) (lrcbuilder * thiz, const char * LRC, size_t lrc_length ); Typedef lrc_result (* lrcbuilderend) (lrcbuilder * thiz ); Typedef lrc_result (* lrcbuilderdestroy) (lrcbuilder * thiz ); Struct _ lrcbuilder { Lrcbuilderbegin on_begin; Lrcbuilderonidtag on_id_tag; Lrcbuilderontimetag on_time_tag; Lrcbuilderonlrc on_lrc; Lrcbuilderend on_end; Lrcbuilderdestroy destroy; Char priv [1]; }; |
Implementation 1:
Lrcbuilder * lrc_dump_builder_new (File * FP) { Lrcdumpbuilder * Data = NULL; Lrcbuilder * thiz = (lrcbuilder *) calloc (sizeof (lrcbuilder) + sizeof (lrcdumpbuilder), 1 ); If (thiz! = NULL) { Thiz-> on_begin = lrc_dump_builder_on_begin; Thiz-> on_id_tag = lrc_dump_builder_on_id_tag; Thiz-> on_time_tag = lrc_dump_builder_on_time_tag; Thiz-> on_lrc = lrc_dump_builder_on_lrc; Thiz-> on_end = lrc_dump_builder_on_end; Thiz-> destroy = lrc_dump_builder_destroy; Data = (lrcdumpbuilder *) thiz-> priv; Data-> fp = FP! = NULL? FP: stdout; } Return thiz; } |
Implementation 2:
Lrcbuilder * lrc_default_builder_new (void) { Lrcdefabuilder builder * Data = NULL; Lrcbuilder * thiz = (lrcbuilder *) calloc (sizeof (lrcbuilder) + sizeof (lrcdefabuilder builder), 1 ); If (thiz! = NULL) { Thiz-> on_begin = lrc_default_builder_on_begin; Thiz-> on_id_tag = lrc_default_builder_on_id_tag; Thiz-> on_time_tag = lrc_default_builder_on_time_tag; Thiz-> on_lrc = lrc_default_builder_on_lrc; Thiz-> on_end = lrc_default_builder_on_end; Thiz-> destroy = lrc_default_builder_destroy; Data = (lrcdefabuilder builder *) thiz-> priv; } Return thiz; } |
Three layers of the class:
The concept of class is quite subtle. Even in the software development field, different people refer to this concept in different ways. Some masters have long noticed this point. To make this concept more accurate under different circumstances, they suggest looking at the concept of class at three levels:
1. Concept layer (conceptual)
This is a high level. It is usually used for domain analysis to establish a conceptual model. The term used in this case is a term in the real world, rather than a term in software development. At this level, a class is just a concept, with some less rigorous feature descriptions, and even only one name. Although it often corresponds to classes in software development, this ing is not necessarily direct.
2. Specification)
At this level, the class is already in the scope of software development, but the main concern is the class interface, rather than the class implementation. At this point, you may think of a group of interface functions, regardless of how these functions are implemented.
3. Implementation Layer (Implementation)
At this level, we can actually implement the struct class. At this time, you may think of some function bodies written in a certain language, defined member variables, and so on.
Benefits of object-oriented:
Object-Oriented programming (AOP), Generative programming (GP), and component-oriented development have emerged over the past few years, they all put forward some new ideas, which greatly improve the development efficiency in some aspects. However, they do not replace object-oriented, but rather supplement and improve object-oriented, object-oriented always sit in the first chair.
How can object-oriented systems replace object-oriented systems? What is the magic of encapsulation, inheritance, and polymorphism? Will it attract many experts to perfect it, so that the evangelists will not bother to praise it? In the final analysis, object-oriented will bring two benefits that designers have been pursuing:
1. Reduce the complexity of the system.
As we all know, with the rapid development of hardware, the computer's computing power is getting more and more powerful, and people expect more and more software, and the complexity of software increases exponentially with its scale. Software complexity can be said to be the first challenge in software development. We can easily write 5000 lines of code. In the face of software with 1 million lines of code, we may feel a little limited in human intelligence.
Object-oriented is a good way to reduce system complexity. First, it organizes the system by class and divides the system into several major parts, each of which is composed of smaller sub-classes, so it can be subdivided until we can easily implement it, this divide-and-conquer approach is in line with the human habit of solving complex problems.
Second, it uses Abstract to specific order to grasp things. abstraction allows us to use a small amount of energy to grasp the commonalities of things, and then study more specific things features, this refined approach is also in line with the human habit of solving complex problems.
2. Isolate changes.
Demand changes and technological changes are also two major challenges for software development. Users never seem to know what their real needs are, and perhaps their real needs are changing. Technology is changing with each passing day. We constantly invent new technologies that help us increase productivity. But sometimes new technologies are hitting our feet. to use these new technologies, we need to spend more time studying and working. Or innovation only satisfies the pleasure of a few people and makes them suffer.
Only change is permanent, and cursing a change does not help. It is the right path to face it and engage it. The master also suggested that we embrace change, rather than escape it. Object-oriented is one of the silver bullets that embrace changes. It does not try to block changes (no one can do anything about it), but tries to isolate them. Compared with the whole, the changed part only occupies a small part after all. If these changes are isolated, they will not affect the unchanged part, this can greatly reduce the trouble caused by changes. Interface Programming rather than implementation programming is the essence of the Surface object and a recipe for embracing change.