Delphi 20 rules for object-oriented programming

xiaoxiao2021-03-06  62

About the author Marco Cantu is a well-known Delphi expert. He has published "Proficient Delphi" series, "Delphi Development Manual" and e-book "Proficient PASCAL" (this e-book can be available free of charge). The topic he taught is Delphi foundation and advanced development skills. You can get more information about him through his website (www.marcocantu.com), you can also contact him with his public news group. Please refer to his website for details.

Introduction Most Delphi programmers use their hand to develop tools like Visual Basic, and don't realize the powerful features of Delphi, and more don't talk about these features. (Write here, editing the fearful raise hand, how can it be?) Delphi and Visual Basic, Delphi is fully built on object-oriented structures, which not only affects the structure of VCL, but also affects every one developed using Delphi. program. In this article, I don't want to involve all the theories of object-oriented programming (OOP), just propose some simple experience rules. I hope these rules can help improve your program structure. Regardless of the type of program you develop, these empirical rules are applicable. You should treat them as some suggestions, remember them and apply them to the program you develop. A key principle I want to emphasize is to be encapsulated on object-oriented programming. We all want to create some flexible and strong classes, because such classes allow us to modify their implementation methods without affecting other parts of the program, this is the benefits of packaging us. Although the package is not a single standard for a good object-oriented program, it constitutes the basis of surface object programming, so I may have too much powerful encapsulation in this article, please don't feel strange, I have enough reasons for it. do. Finally, I want to explain such a fact that this article will focus on the development of the form (although some of these rules apply to components), these rules are suitable for all Delphi programmers. The programmers who write components must program the surface objects and classes as the core of the core, but for those programmers who use components, they often forget the object-oriented. For them, this article can be treated as a prompt, reminding them to remember object-oriented programming

Part 1: Form is a class (Rule 1-Rule 15) programmer often treats the form as an object, and the fact form is class. The difference between the two is to create multiple form objects based on the same form class. What is doubtful is that Delphi creates a default global object for each form class you defined. This is quite convenient for novices, but this will also make them form bad habits.

Part II: Inheritance (Rule 15-Rule 20) In the second part, the second part will be some of the inheritance of the class and the inheritance of the class, especially the form of the form, in particular about the form. And skills.

About Code All code segments in this article can be found in the OOPDemo project in the disk included in the Delphi Magazine "ISSUE 47). You should especially look at the FRM2 unit (Unit) and Inher units in the routine. If you want to use these code, please note the necessary initialization settings of the constructor and the private component reference, and it is necessary to set the OldCreateOrder properties of the form. Otherwise, the initialization code of the form constructor will be executed before the form's oncreate event. On this disk you can also find the first edition of the OOP Form Wizard, but I want you to visit my website to get the more complete version of the program. Rule 1: Create a unit (One Class, One Unit) for each class, keep this: Private and protection (Protected) part only for classes and processes in other cells (procedure) Hidden. So if you want to get effective encapsulation, you should use a different unit for each class. For some simple classes, such as those that inherit other classes, you can use a shared unit. However, the number of classes that share the same unit is limited: don't place more than 20 complex classes in a simple unit, although Borland's VCL code has been doing so. If you use a form, Delphi will default to follow the rules of "a class using a unit", which is also very convenient for programmers. When you add a class without a form to your project, Delphi creates a new independent unit. Rule 2: It is important to give each form and unit for each form and unit. The names of the form and unit must be different, but I tend to use similar names for them, such as using AboutForm and About.PAS for them, using the descriptive name for the component. It is also very important. The most common naming method is to start using the lowercase of the class, plus the components, such as btnadd or editname. With this naming method, there will be a lot of similar names for component naming, and there is no best name. In the end, it should be chosen that should be based on your personal hobbies.

Rules 3: Name Event is more important for event processing methods to give appropriate names. If you give a proper name for the component, the system default name ButtonClick will turn btnaddClick. Although we can guess the function of this event handler from this name, I think it is a better way to use a name that describes the role of the method, not the name of Delphi attached is a better way. For example, the BTNADD button's onclick event can be named ADDTOLIST. This will make your program more readable, especially when you call this event handler in other methods of this class, and this helps programmers use the same way to similar events or different components. But I have to declare that the action (Actions) is my favorite approach when developing important procedures.

Rules 4: Use Form Methods Forms All class, so the form of the form is organized in methods. You can add event handlers to the form that completes some special features, and they can be called by other methods. In addition to the event handling method, you can add a specially defined method for the form and a method of accessing the form state. Add some public (public) methods to other forms to other forms to do his components directly than other forms.

Rules 5: Add Form Constructors, the second form created at runtime, except for a default constructor (inherited from Tcomponent class), other special constructors will also provide other special constructors. If you don't need to consider compatibility with Delphi4 previous version, I suggest you overload CREATE method to add the necessary initialization parameters. Specific code can be found in the following code: Public Constructor Create (Text: string): reintroduce; overload; Constructor TformDialog.Create (Text: string); Begin Inherited Create (Application); Edit1.Text: = Text; End; Rule 6: Avoid Global Variables should avoid using global variables (that is, those defined in units of Interface section). There will be some suggestions to help you do it. If you need to store additional data for the form, you can add some private data to the form class. In this case, each form instance has its own copy of the data. You can use unit variables (variables defined in units of the unit) declare those shared by multiple instances of the form. If you need to share data between different types of forms, you can define them in the main form to achieve sharing, or use a global variable, how to use methods, or attributes to get data. Rule 7: Never use Form1 in the TForm1 class (Never USE Form1 in TForm1) You should avoid using a specific object name in the class, in other words, you should not use Form1 directly in the TForm1 class. If you really need to use the current object, you can use the Self keyword. Keep in mind: Most of you don't have to use the method and data of the current object directly. If you don't follow this rule, when you create multiple instances for a form class, you will fall into trouble.

Rules 8: Try to avoid using Form1 in other forms, even in other forms of form, you should try to avoid direct use of global variables, such as Form1. Define some local variables or private domains For other forms, it will be better than the direct call global variable. For example, a program's main form can define a private domain for a dialog. Obviously, this rule will be very useful if you plan to create multiple instances for a derived form. You can keep a list within the code range of the main form, or you can easily use the form an array of global SREEN objects.

Rules 9: Remove Form1 (Remove Form1) In fact, my suggestion is to remove the global form object that Delphi automatically created in your program. This is also possible even if you prohibit the automatic add function of the form, because this form may still be added in Delphi. The suggestion for me to give you should try to avoid using a global form object. I think it is useful for Delphi's newcomers, which is useful to remove global form objects so that they are not confused about the relationship between classes and global objects. In fact, after the global form object is removed, all the code related to it will generate errors.

Rules 10: Add form property, as I have mentioned, when you need to add data to your form, add a private domain. If you need to access other classes, you can add properties to your form. Using this method You can change the code and data of the current form (included in its user interface) without having to change the code of other forms or classes. You should also use attributes or methods to initialize the partial form or dialog, or access their final state. As I said before, you should use the constructor to complete the initialization work rule 11: Display component properties (EXPOSE Components Properties) When you need to access other forms, you should not access its components directly. Because this will combine other forms or other classes and user interfaces, and the user interface is often the most prone to change in an application. The best way is to define a form properties for the component properties you need to access. To achieve this, you can implement the set method of the component state and the set method of setting component status. If you need to change the user interface now, replace existing components with another component, then you only need to modify the GET method and SET method related to this component properties, do not have to look up, modify all references to this component. Source code for class. See the detailed implementation method of the following code: private function GetText: String; procedure SetText (const Value: String); public property Text: String; read GetText write SetText; function TformDialog.GetText: String; begin Result: = Edit1.Text; End; Procedure TFORMDIALOG.SETTEXT (Const value: string); begin edit1.text; = value;

Rule 12: ARRAY Properties If you need to handle a series of variables in the form, you can define an attribute array. If these variables are some information about the form, you can also define them to form an array of properties of the form, so you can use Specialform [3] to access their values ​​directly. The following code shows how to define an item of a ListBox component into a form default attribute array. type TformDialog = class (TForm) private listItems: TlistBox; function GetItems (Index: Integer): String; procedure SetItems (Index: Integer: const Value: String); public property Items [Index: Integer]: string; end; function TFormDialog .GetItems (Index: Integer): string; begin if Index> = ListItems.Items.Count then raise Exception.Create ( 'TformDialog: Out of Range'); Result: = ListItems.Items [Index]; end; procedure TformDialog. Setitems (index: integer; const alue: string); begin if index> = listitems.items.count the Raise Exception.create ('tformdialog: out of range'); ListItems.Items [index]: = Value;

Rules 13: Use the Additional Side-Effects In Properties to remember: One of the benefits of using properties instead of accessing global variables (see Rule 10, 11, 12) is to set or read the value of the attribute. When you may not intend to gain. For example, you can directly drag the components directly on the form interface, set the value of multiple properties, call special methods, change the state of multiple components, or revoke an event (if needed), etc..

Rule 14: Hide Components I often hear those mad pursuits that are object-oriented to the Delphi form that contains some components declared in the Published part, which is incompatible with the encapsulation principle of object-oriented ideas. They did put forward an important topic, but most people in them did not realize that the solution was actually on their hand, without rewriting the Delphi code, nor will they turn to other languages. The components added to the form can be moved to the Private section such that other forms cannot access them. If you do this, you will need to set some form properties to the component (see Rule 11) and use them to access the status of the component. Delphi puts all of these components in the Published section, because this way can ensure that these domains must be created in the .dfm file. When you change the name of a component, VCL can automatically associate this component object with it in the form. Because Delphi uses the RTTI and TOBJECT methods to implement this function, if you want to use this automatic implementation, you must place the reference to the Published section (this is why Delphi puts all the components in the Published part. ). If you want to know more details, please refer to the following code:

procedure Tcomponent.SetReference (Enable: Boolean); var Field: ^ Tcomponent; begin If Fowner <> nil then begin Field: = Fowner.FieldAddress (Fname); If Field <> nil then Field ^: = Self else Field ^: = NIL; end;

The above code is the SetReference method for the Tcomponent class, which can be called by INSERCOMPONENT, REMOVAMPONENT, and SETNAME. When you understand this, you should not think that if you move the component reference from the Published section to the privated segment, you will lose the automatic accessibility of the VCL. In order to solve this problem, you can add the following code in the form's oncreate event: edit1: = findcomponent ('edit1') as tedit; you should do next is to register these components in the system, when you are After they registered, they can enable RTTI into the compiler and can be used by the system. When you move these types of components to the Private section, you only need to register them once for each component class. Even when registration is not necessarily necessary, you can do this because additional calls for RegisterClasses are beneficial. Usually you should be responsible for generating a form of an initialization section of the unit to add the following code: RegisterClass ([TEDIT]);

Rules 15: THE OOOOP FORM WIZARD Repeats the two operations for each component of each form not only very annoying, but also quite wasting time. In order to avoid additional burden, I have written a simple wizard program for this. This program will generate some code that can complete the above two steps, and you need to do it several times to copy and paste it. Unfortunately, this wizard program cannot automatically place the code in a suitable place in the unit. I am currently modifying this wizard, I hope to implement this feature. You can find more complete programs to my website (www.marcocantu.com). Rule 16: Visual Form Inheritance, if applied, this will be a powerful tool. According to my experience, the bigger the project you have developed, the more it can reflect its value. In a complex program, you can use the different level of relationship of the form to process a polymorphism of a group of related forms (Polymorphism). Visual form inherits allows you to share some public actions of multiple forms: You can use shared methods, common properties, even event handlers, components, component properties, component event processing methods, and more.

Rules 17: Limit Protected Data (Limit Protected Data) When you create some classes with different hierarchical systems, some programmers tend to primarily use protected domains because private data cannot be accessed by subclavab. I can't say this doesn't matter, but this is definitely incompatible with encapsulation. The implementation of the protection data can be shared by all inherited forms, and once the original definition of this data changes, you must change all related parts. Note that if you follow a rule such as hidden components (Rule 14), inheriting the form is impossible to access the private component of the base class. In a inheritance form, the code like edit1.text: = '' will not be compiled. Although this is quite inconvenient, at least in theory this is worthy of affirmation, not a negation. If you feel that the encapsulation is the most important, you need, please refer to the private segment of the base class.

Rules 18: Protected Access Methods in the base class in the base class in the private domain, and add some access functions to these components to get their properties, which will be a better way. . If these access functions are only used inside these classes and is not part of the class interface, you should declare them in the protection domain. For example, the GetText and SetText methods described in Rule 11 can be declared as protected and we can edit text by calling setText (''). In fact, when a method is mirrored to an attribute, we can simply use the following code to reach the editing text: Text: = '';

Rules 19: Protected Virtual Methods in the domain to implement a flexible hierarchical system is that some virtual methods you can call from external classes can be obtained. If this method is used, it will raise a situation in which other public methods call the virtual method in the protected domain. This is an important trick because you can customize the virtual method of the party to modify the action of the object.

Rule 20: Virtual Methods for Properties (Virtual Methods for Properties) Even if the method of access attribute can be defined as Virtual, the derived class can change the actions of the property without having to define them. Although this method is rarely used in VCL, it is indeed very flexible and powerful. In order to achieve this, just the need to define the GET and SET methods among Rule 11 as Virtual. Base class code as follows: type TformDialog = class (TForm) Procedure FormCreate (Sender: Tobject); Private Edit1: Tedit; Protected function GetText: String; virtual; procedure SetText (const Value: String); virtual; public constructor Create (Text: string): Reintroduce; OVERLOAD; Property Text: String ReadText Write SetText; End; In inheritance form, you can add some extractions to overload virtual methods setText: procedure tforminherit.settext (const value: string Begin inherited settext (value); if value = '' Then Button1.enabled: = false;

转载请注明原文地址:https://www.9cbs.com/read-111813.html

New Post(0)