Avoid using ClassName to determine the type of type in Delphi

zhaozj2021-02-16  66

In the code of the company's original system, I saw a lot of ClassName attributes for the discriminant objects to process the code. Moreover, it seems to be a standard method for dealing with similar problems. But there may be some problems.

First, we know that the polymorphism is one of the three major characteristics of objects. The so-called polymorphism, its idea is that for different specific types, we can access the same abstract interface without having to relate specific types of implementation details. Just as the next notice: All employees are gathered at People's Square tomorrow. Don't need to specifically notify each person living in different locations, should you start, what is the route, because this is the responsibility of the specific person, not the responsibility of the next person. Therefore, when writing to the need to determine the ClassName to perform separately, the method of processing should first be thought in adding an interface in the parent class and is done by subclass Override. Changes to the size of the graphic size below: for i: = 0 to graphic list .count - 1 do beg graphics: = Graphic list [i]; if graphic .classname = 'rectangular' The Begin rectangle (graphic). Long: = Rectangular (graphic). Long * 2; rectangular (graphic). Wide: = rectangular (graphic). Width * 2; ELSE IF graphic .classname = 'circular' Then Begin circular (graphic). Radius: = rectangle ( Graphics). Radius * 2; end end; you can add "change" method in the parent class "graphics", the code is the following graphics = Class ... procedure Changesize (rate: integer); virtual; end; rectangular = class ... procute Changesize (rate); override; end; circular = class ... procedure change; end; END; implement size changed code in a specific graphics class: Procedure Rectangle .changesize (Rate: integer) : Begin length: = long * Rate; width: = width * rate; end; procedure round .changesize (rate: integer); begin radius: = radius * Rate; end; This modified, the above code can be called : For i: = 0 To graphics list .count - 1 do beg graph: = graphic list [i]; graphic .changesize (2); END; this code is clear.

Of course, in many cases, it is not possible to use the solution to the ClassName. For example, traversing the Form's COTROLS and initiates different controls. We cannot add initialization methods to tControl, and only identify specific subclass types. Then, I recommend using IS operators instead of directly comparing classname. IS usage, statement AObject is TForm In different ways of different AObject, the results are as follows: AObject is the result is false; AObject is TFORM, the result is true; AObject is TFORM1, the result is true; AObject is TEDIT, the result is a fake AObject is NIL, resulting in a false; from the above example, one of the advantages of IS can be seen, IS can determine whether the subclass of subclasses,, for example, when we initialize the control, it is dependent whether it is TIMAGE or TEDIT to make different initialization, through IS judgment deal with. In the future, I will use TCOOLEDIT to beautify the interface, then this code doesn't need to be changed, because a TCOOLEDIT is a TEDIT; and if ClassName must be changed to the name of the subclass. Second, if the object being determined is likely to be empty, use the classname to determine whether the object must be judged whether or not the object is assigned, otherwise the memory access error will appear. The determination representative must be written as: if Assigned (AObject) and AOBject.className = 'tclass1'; uses IS only needs to write to if Aobject IS TCLASS1. The last reason is that the ClassName is used as a determination is that the classname is only used to describe the properties of a class, and the string cannot be checked in the compile period. If there is a spelling error, or the case code will appear logic errors, and this Errors are only found when running to this statement during the running period. If acontrol.classname = 'teidt' Then// only checks this code when you notice that Edit does not have initial test; if acontrol is teidt life // cannot be compiled;

As described above, when it is necessary to determine a specific type of object, first, it should be considered to avoid this statement of the specific processing by polymorphism, which should not be avoided, and the IS operator should be judged, not ClassName. In a very special case, IS may not be able to get the desired result, such as the situation that needs to handle TEDIT and TCOOLEDIT, and uses IS, and the Cooledit will also judge TEDIT. At this time, the CLASSTYPE method can be used. String comparison of type detection: acooledit is tedit // true; acooledit.classtype = tedit // false; acooledit.classtype = tcooledit // true;

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

New Post(0)