| Basics of the construction and functionality of HSOK: THSObject class |
|
| 20 June 2007 | ||||||||||||||||||||||
Page 4 of 9 THSObject classTHSObject class, inherting from THSBaseObject introduces mechanisms of object fields management and memory used by them. Fields supported by HSOK are implemented as a list of references to objects representing them. Only fields that actually have values are kept in memory. These fields as well as the list of references to them are allocated automatically with the first write access to a field. This means that in HSOK an empty object does not utilize memory, on the contrary to e.g. records or classic objects that always allocate memory for all its fields. THSObject class also implements HasValue property declared in THSBaseObject, addressing the problem of NULL values in object fields. To do this it uses an array FHasValue of THSByteArray type, which stores information about fields having value. Each field is represented by one bit. The array is reallocated dynamically when needed, with succesive write access to fields. It saves memory, especially when out of a few tens of fields we use only first several. That is why it is better to declare the most frequently used fields at the beginning of an object. THSObject class defines read/write methods for primitive types, supported by THSStringField, THSByteField, THSSmallIntField classes etc. The field itself is defined in the section "published" of a class as an array property with a declared index, which corresponds to the position of the field in the fields list of the class, e.g.: property Name : string index idxName read GetHSStringField write SetHSStringField; where idxName is a constant declared in the section "const" of the class module. The set method SetHSStringField creates the field if it does not exist and then sets its value. The get method GetHSStringField returns value of the field or default value (in this case an empty string) when the field does not exist (actually has a NULL value). All other fields are supported in the same way. This mechanism saves memory and simplifies the coding process because the whole memory management is done in the "background". For example we can write: Car.Engine.Gearbox.Pulley.Diameter := 23; and be sure that if subobjects Engine, Gearbox, Pulley and the field Diameter did not exist they just have been created (note that this is the case of setting a value). We can acces fields also by the Fields property, which allows us e.g. to iterate objects representing fields in a loop. Methods FieldClassByIndex, FieldSizeByIndex, FieldNameByIndex, FieldIndexByName are Delphi's RTTI mechanisms correspondents. They are overridden in descedants and their content is generated and optimized automatically by the Class Editor. Thanks to optimization (e.g. binary search in FieldIndexByName) they work faster than corresponding Delphi's RTTI mechanisms. Finding a field of a given name quickly is essential for fast reading of text and XML files (see HSOK vs InstantObjects™). Along with LastUsedField, FieldIndexByRef, FieldByName these methods simplify creation of generalized algorithms operating on objects of different classes - e.g. methods for saving any object in a relational database or generating an edit form when requested. Object data proccessing is simplified by methods :
Arguments of ClearFields, ClearFieldsExcept, CopyFields etc. methods can be numbers, field names or even paths to them which allows us to write: DataSADUE.ClearFields(['SADPosition[?].NCTSData.P17DestinationCountry']); which means "clear the field P17DestinationCountry of the field NCTSData in all elements of the SADPosition list". The same could be done by :
The first example is pretty short and obvious. It works much slower though, because the path to the field must be analyzed in runtime. We recommend it in application proptotyping or in cases, where efficiency isn't essential. |
||||||||||||||||||||||





