Analysis of the polymorphic 1 in delphi? 21.1 Concept 21.2 Polymorphism 21.3 How is the polygon in Delphi implementation? 21.3.1 Inheritance 21.3.2 Dynamic Method, Dynamic Method and Abstract Method, VMT / DMT, Static Binding and Dynamic Binding 21.3.3 Overload and Polymorphism 21.4 Discussion 21.4.1 Two-stage polymorphism 21.4.2 Unsafe Polymorphism 22 VCL Diversity Application 22.1 Construction and Design Method 22.2 Tstrings 22.3 Others (please add) 2 Abstract polymorphism is the object-oriented soul, understanding polymorphism It is one of the key to object-oriented technology. This paper focuses on the basic principles of polymorphology, the essence of polymorphism, and the application in VCL. Keyword polymorphism, inheritance, object-oriented, VCL, virtual method (Virtual Method), override
The problem is the object-oriented soul, and understanding the polymorphism is one of the key to object-oriented technology. But what is more? What is the meaning of polymorphism? How to achieve polymorphism? I can understand the concept, but I don't know how to use and what should I use? Please see this article. Experts analyze the heavens and earth creatures (objects, ie objects), thousands of changes; in the computer world, only one line of machine instructions, the two seem to have no coherent, in the past, it is very difficult to describe the real world with computer language. Things, although some people write out of the object to the object with C language, I dare to determine that it is extremely cumbersome until the ariented-object referred to as oo), everything will change, the entire software industry has occurred. The earth-shaking change begins with a series of programming languages, a series of object-oriented programming languages (OOP) such as SmallTalk, C , Java, Object Pascal, C #, etc .; all kinds of object-oriented development tools have also emerged as VC, Delphi , BCB, JBuilder, etc., and many excellent libraries such as VCL, .NET Framework, and some business class libraries, etc., the development of object-oriented design (OOA), object-oriented databases, and object-oriented databases (OODB), object-oriented technology almost through the entire software field, the programmer's thinking also has undergone fundamental changes! In some OO purification, everything is an object! Although I don't fully agree with this view. But I think this way is most in line with people's thinking habits. It makes programmers to concentrate on business logic, and complete the transformation of object-oriented to machine instructions (completed by object-oriented compilers), programmers Since this is liberated! This is a revolution! Object-oriented core content is object, encapsulation, inheritance, polymorphism, and message mechanism, which is to describe the diversity of the real world, and it is the most important feature of objects, which can be said, do not master the polymorphism, There is no truly object-oriented technology. 1 What is a multi-state? 1.1 Concept of conceptual polymorphism, the following is a few representative statements: "This Ability to manipulate more Than One Type with a pointer or a reference to a base classis spoken of as polymorphism" ("C Primer" page 838) . That is, the ability to operate multiple types (base classes and their partial categories) with a pointer / reference for a base class is called a polymorphism. It is considered from the perspective of language implementation. "Polymorphism Provides Another Dimension Of Separation of Interface From Implementation, To Decouple What from How" ("Think in java" 3rd edtion), it is a polymorphically provided another separation interface and implementation (ie, what to do "and" Do a "separate) of a scale. It is considered from the perspective of design. "The Ability to Use the Same Expression to Denote Different Operations IS Refered TO As Polymorphism", ("Object-Oriented Methods Principles & Practice" 3rd Edition, page 16). Simply put, polymorphism is "the same expression, different operations", or "the same command, different operations". This is seen from the perspective of object-oriented semantics.
Three statements have elaborated from different angles, respectively. The third statement is especially true, and the third statement is focused below. First explain the meaning of this sentence: the same expression - function calls different operations - there are different operations according to different objects. For example, an example is for example, there are various duties in the company (programmers, salesperson, clause, etc.), when they "go to work", do different things (can also be seen as a business logic) We have abstracted their respective tasks as "work". The relationship is as follows: Employees / | / - Inheritance Profile Programmad, the businessman's business manager is at work every day, it is equivalent to sending such a command: "employees. Beginning to work "(the same expression) After each employee receives this command (the same command)," start working ", but they do their work, the programmer begins" Coding ", the salesman Start "Contact Business", the manager begins "finishing the document." That is, "the same expression (function call), (executable at the runtime) different operations according to different objects." From a language-implemented polymorphism, the polymorphism is implemented by the base class pointer or the reference to the target class, calling its virtual method. Below is the implementation of the Object Pascal language temployee = Class // Abstract the employee to an abstract class public procedure startworking; virtual; Abstract; {abstract function (ie, pure virtual functions in C ), nothing, the actual meaning is, first Reserve an interface. On its derived class to carry it up. } End; tprogram = class (temployee) // programmer public procedure startworking; override;
Tbusinessman = class (temployee) // Salesman Public Procedure Startworking; Override; End;
TDOCMANAGER = Class (Temployee) // Clause Public Procedure Startworking; Override; End; Procedure TProgram '; SHOWMESSAGE (' Coding ');
{TBusinessman}
Procedure tbusinessman.startworking; begin ShowMessage ('linking business "; end;
{TDOCManager}
Procedure tdocmanager.startworking; begin showMessage ('managing document');
procedure TForm1.Button1Click (Sender: TObject); const eNum = 3; var Employee: array of TEmployee; i: integer; begin setLength (Employee, eNum); Employee [0]: = TProgramer.Create; // reference to the base class Employee [0] points to the TPROGRAMER object Employee [1]: = tbusinessman.create; // Pointing the base class reference EMPLOYEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE [1] points to the TBusinessman object Employee, which is just created [2]: = TDOCManager.create; // Class reference EMPLOYEE [2] points to the TDoCManager object for the just created for i: = 0 to length (Employee) -1 do Employee [i] .Startworking; // Dynamically bind the corresponding method based on the actual object type according to the actual object type. {Polymorphism from the language, the polygon is implemented by the base class pointer or the reference to the target class, calling its virtual method. Employee [] is a base class object reference array, and its members point to different derived class objects. When the modified virtual method is called, I realize the polymorphism} END; try that you can type some code (or DEMO program), and Compile operation, click on the button to see the magical effect of polymorphism.
1.2 The meaning of the polymorphic package and inheritance is that they have realized the code reuse, and the polymorphism is that it implements the interface reuse (the same expression), the advantage of the interface reuse is more easy to expand, code reuse More convenient, more flexible, can truly reflect the real world. For example, in order to better manage, divide the programmer into C programmer, Delphi programmer. ... Employee / | / - Inheritance Programmer Salesman Classist / / - Inheritance C Programmer Delphi Programmer After the programmer adds TCPPROGRAMER, TDELPHIPROGRAMER two derived classes, the way the call is still changed, or "employee We started to work, describe using Object Pascal: ... setlength (Employee, ENUM 2); Employee [enum]: = tcppprogram.create; // Create a TcppProgramer object, and put the base class reference Employee [enum] point to it Employee [Enum 1]: = TDELPHIPROGRAMER.CREATE; ... {Employees. Beginning to work} for i: = 0 to length (employee) -1 doemPloyee [i] .Startworking; // or the same call method (because of the interface Unchanged). ... 1.3 How does polymorphism implementation in Delphi? The necessary conditions for achieving polymorphism are inheritance, virtual methods, dynamic bindings (or lag wedges), how is Delphi to achieve polymorphic? 1.3.1 Inheritance inherits the "Ako" between the species and classes A Kind of, is a) "relationship, such as programmer" is a "employee represents a inheritance relationship. In Delphi, only support only inheritance (without the multiple inheritance of the interface), although there is no more inherited flexibility, it has brought us great benefits, where we can have a base class in any The object's place can be used instead (in turn), this is the so-called "polymorphic replacement principle", we can assume the address of the derived object to the base class / reference, for more The state provides a prerequisite. In UML: AKO: A Kind of Indicates Inheritance Relationship APO: A Part of Representation ISA: IS A Representation The relationship of the object and the class 1.3.2 virtual method, dynamic method and abstract method , VMT / DMT, static binding and dynamic binding For all methods, there is no trace in the object. Its method pointer (inlet address) is saved in the class, and the actual code is stored in the code segment. For static methods (non-virtual methods), the inlet address of the object method directly by the compiler directly according to the reference type of the object, this is the so-called static binding; and for the virtual method, because it may be overloaded, when compiling The compiler cannot determine the actual class, so only the entry address of the method is determined by the VMT table entry address (ie the first four bytes of the object) in the runtime, which is a so-called dynamic binding (or hysteracted). The virtual method is virtual method, indicating a method that can be override. If it is not declared as an abstract method, it is required to provide a default implementation in the base class. In addition to the stored virtual method pointer, the class is stored, and the virtual method pointer of all base classes is also stored.
Declaration method: Procedure method name; Virtual; This is equivalent to telling the Delphi compiler: can be overridden in the derived class (OVERRIDE) or the false method. Do not determine the entry address of the method when compiling. In the runtime, the entry address of the method is determined by dynamic binding. Provide a default implementation in the base class, if there is no override method in the derived class, use the default implementation in the base class. Dynamic method dynamic method and virtual method are essentially, different from the virtual method, the dynamic method only stores its own dynamic method pointer in the class, so the virtual method is much more memory than the dynamic method, but it performs faster . But this is entirely transparent to the user. Declaration method: Procedure process name; Dynamic; Abstract method a special virtual method, in the base class does not need to provide the default implementation, just a call interface, equivalent to the pure virtual function in C . The class contains the abstract method, called an abstract class. Declaration method: procedure process name; Virtual; Abstract; VMT / DMT In Delphi, virtual method table (VMT), in fact, it is not physically, to better explain polymorphism, people are logical Give it a definition, in fact it is just a collection of the address of the false method in the class, which also includes the virtual method of its base class. "VMT entry address" stored in the first four bytes of the object, actually the address of the class it belongs (refer to the DEMO program). With the actual class, and method names can find the virtual method. Obj (object name) actual object belongs to class VMT entry address data member class unity method VMT entry address data member template information static method equivalence method (VMT) dynamic method (DMT)
Figure 3 object name, object and class relationship DMT and VMT are similar, are also logically a concept, different, only saving its own dynamic method pointer, without the address of the base class, this saves Some memory, but the speed is not as good as the virtual method, is a strategy sacrificing time-to-room, generally not recommended. Quote the above example to explain: Employee [i] .Startworking; Employee [i] is an object reference to the base class TemPloyee, with the above program knows that it may point to a TPROGramer object, or it may point to a TBusinessman, It is possible to be other objects, and these are uncertain, dynamic, so they cannot know the actual object when compiling, the method address is not determined. At the course of operation, of course, I know the "Lushan true face" of the object. According to the content of the first four bytes of the actual object, it is the entry address of the virtual method table VMT, find the actual call, that is, the polymorphism. 1.3.3 Overloading and multi-state a lot of netizens think that the function overload is also a polymorphism, is there. For "different operations", the overload cannot provide the same way, although the function name is the same, but its parameters are different! Realizing the premise of polymorphism, is the same expression! Such as Employee [i] .StartWoring, and overloaded calls, there are different parameters or parameter types. Overload is only a language mechanism, and there is also overload in C language, but the C language is not polymorphic, and the C language is not object-oriented programming language. Unless the overload function is also virtual method, otherwise the compiler can determine the entry address of the function according to the type of parameters, or static binding! "Don't make silk, if it is not dynamic binding, it is not a polymorphism." 1.4 Discussion on the species of the species 1.4.1 Two-stage polymorphism-level: Use the base class pointer / reference to its derived class object, call the virtual method (or dynamic method, abstract method), which is used. Type: Use class reference (reference to the class rather than the object) points to the derived class, call the virtual class method (or dynamic method, abstract class method), often used in the object (because the construct method is a kind " Special "class methods, please refer to my other" Analysis of the Construction and Destruction and Destruction of Delphi ", Section 2.1). The presentation class reference is the reference variable of the class itself, not a class, not an object reference. Just as the object name represents an object reference, the class name represents a class reference, because in Delphi, the class is also processed as an object. The class reference type is the type of class reference, the class reference type declaration method: class reference type name = Class Of class name We can see a lot of categories in the source code of the VCL, such as: tclass = class of tobject; TcomponentClass = Class of Tcomponent; tcontrolclass = class of tcontrol; Note In the class method, the Self is hidden in the method, is a class reference, not an object reference.
1.4.2 Unsafe Polymorphical Pointer Pointer / Reference Pointing To the base class can also achieve polymorphism! Although this is an error: procedure tform1.btnbadpolyclick (sender: Tobject); var cppprogram: tcppprogramer; / / Define a CPP programmer reference, a derived reference! Begin {************************************** *********************************************************************************************************************************** It is a pathological polymorphism! This polymorphic use method is like an actual very small thing (base class object), which has a strong appearance (derived class reference), which has brought many potential not Security factors (such as accessibility), there is almost no value. Such an example of "Du" is intended to illustrate the nature of the polymorphism in Delphi: the use of a legal (usually base class) pointer / reference to operate the object, according to the actual object, To perform different ways, or more image: By the object you decide yourself, the compiler only needs to do what to do (what to do), don't manage how to do (how), "how to do" By being responsible for the object yourself. This achieves the separation of the interface and implementation, making the interface reuse possible. *********************************************************** *********************} cppprogramr: = tcppprogramr (tprogramr.create); {To achieve this morbid polymorphism, the object reference is forced to convert to TCPPROGramer type Thus, escape the compiler's check} cpppprogram.startworking; {called TPROGramer.Startworking instead of tcppprogramer.Startworking This is the polymorphism that is implemented with the base class object with the derived class pointer / reference. } Cppprogram .free;
CppProgram: = TCPPROGRAMER (TDOCManager.create); cpppprogram.startworking; {Calling is turning tdocmanager.startworking, which is the polymorphism that is implemented with the base class object with the derived class pointer / reference. This method is extremely unsafe, and there is nothing necessary} cpppprogramer.free; end; try to get this polymorphic sense of sensibility, it is recommended to try, saying that this method will have potential insecure (If you have an exception), the above program runs a little error, think about why? Under what circumstances, the access exception will appear, and write an example of accessing an exception, you will harvest more. (Reference Demo Program) 2 VCL Diversity Application 2.1 Structure and Design Method Construction Method Structure Since the construction method can be seen as a "special" method, all derived classes after Tcomponent are redefined as The virtual method, so the polymorphism of the construction method is to be used, and there is a class reference. There is a classic example in Delphi, there is a similar code in each project file: Application.createform (TFORM1, Form1); definition of its method: Procedure Tapplication.createform (InstanceClass: TcomponentClass; var REference); var // instanceclass is a class reference. Instance: Tcomponent; Begin Instance: = Tcomponent (InstanceClass.NewInstance); Declaration of {NewInstance method: Class Function newinstance: TOBJECT; Virtual; (System Unit 432 Row) is a class method, and it is also a virtual method, we call it For the virtual class method. InstanceClass is a class reference that implements a class-level polymorphism, thereby implementing the interface reuse of creating components} tComponent: = instance; try instance.create (self); // Call the constructor, perform initialization Except Tcomponent (Reference): = nil; // Eliminate "wild" pointer! Good raise; end; {If you create a window and there is no main form, set the original form to the main form} IF (Fmainform = NIL) THEN BEGIN TFORM (Instance) .HandLeneeded; Fmainform: = TFORM (Instance); // Setting the main form {In fact, set the main form in the project option (Project-> Options), actually mention the corresponding form statement in the project file All created a form statement before. } END; END; 2) Polymorphism of the descent method Refer to "Structure and Destructure in Delphi", Section 3.3 2.2 Tstrings String String Processing is very common in Delphi control, usually some items properties, we It is also particularly convenient (because all the same use interface), it is designed to design the architecture of the character string array in Delphi. This is a successful design. Since there are many controls to use strings arrays, such as ComboBox, TstringGrid, etc., the number of strings in each control is different, and Delphi thus strings, but abstract, there is a lot of related classes. .
Among them, the base class TStrings is only provided to provide an interface to various calls, and the specific implementation can be implemented in its derived class, so the TStrings is defined as an abstract class.
Let's take a look at the common method of the base class TStrings class (see class 442): tstrings = class (tpersistent) protected ... function get (index: integer): string; virtual; abstract; procedure put Index: Integer; Const S:, Virtual; Function GetCount: Integer; Virtual; Abstract; ... public function add (const s: string): integer; virtual; // actually call INSERT {Add a string S to String list} Procedure addstrings (strings: tstrings); virtual; {Add String list strings to this string list} Procedure Insert (index: integer; const s: string); virtual; abstract; {Abstract method, in Inserts of the INDEX position S} procedure clear; virtual; abstract; {Clear all string} procedure delete (index: integer; {Delete String in a location} Function Indexof (const) S: string): Integer; virtual; {S acquired position in the string list} function IndexOfName (const Name: string): Integer; virtual; {Returns the position of the first string with the form Name = Value with the specified Name Part} function indexofobject: integer; virtual; {Get As named AObject: object position in the string list} procedure LoadFromFile (const FileName: string); virtual; {Fills the list with the lines of text in a specified file} procedure LoadFromStream (Stream: TStream); virtual; {Fills the list with lines of text read from a stream} procedure SaveToStream (Stream: TStream); virtual; {Writes the value of the text property to a stream object} property Strings [Index: Integer]: string read Get write Put; default; {References the strings in the list by their positions} property Values [const Name: string]: string read GetValue write SetValue; {Represents the value part of a string associated with a given Name, on strings with the form Name = value } ... End;