Mega Code Archive

 
Categories / Delphi / Ide Indy
 

Language and Compiler Features Since Delphi 7

Title: Language and Compiler Features Since Delphi 7 Question: Language and Compiler Features Since Delphi 7 Answer: Language and Compiler Features Since Delphi 7 Inline The Delphi compiler allows functions and procedures to be tagged with the inline directive to improve performance. If the function or procedure meets certain criteria, the compiler will insert code directly, rather than generating a call. Inlining is a performance optimization that can result in faster code, but at the expense of space. Inlining always causes the compiler to produce a larger binary file. The inline directive is used in function and procedure declarations and definitions, like other directives. Note : The inline directive is a suggestion to the compiler. There is no guarantee the compiler will inline a particular routine, as there are a number of circumstances where inlining cannot be done Syntax example: function AnsiCompareStr(const S1, S2: string): Integer; inline; Operator Overloading Delphi allows certain functions, or operators, to be overloaded within record declarations TMyClass = class class operator Add(a, b: TMyClass): TMyClass; // Addition of two operands of type TMyClass class operator Subtract(a, b: TMyClass): TMyclass; // Subtraction of type TMyClass class operator Implicit(a: Integer): TMyClass; // Implicit conversion of an Integer to type TMyClass class operator Implicit(a: TMyClass): Integer; // Implicit conversion of TMyClass to Integer class operator Explicit(a: Double): TMyClass; // Explicit conversion of a Double to TMyClass end; // Example implementation of Add class operator TMyClass.Add(a, b: TMyClass): TMyClass; begin ... end; // Example using Add class operator Procedure DooStuff; var x, y: TMyClass begin x := 12; // Implicit conversion from an Integer y := x + x; // Calls TMyClass.Add(a, b: TMyClass): TMyClass b := b + 100; // Calls TMyClass.Add(b, TMyClass.Implicit(100)) end; Class Helpers A class helper is a type that - when associated with another class - introduces additional method names and properties which may be used in the context of the associated class (or its descendants). Class helpers are a way to extend a class without using inheritance. A class helper simply introduces a wider scope for the compiler to use when resolving identifiers. When you declare a class helper, you state the helper name, and the name of the class you are going to extend with the helper. You can use the class helper any place where you can legally use the extended class. The compiler's resolution scope then becomes the original class, plus the class helper. Class helpers provide a way to extend a class, but they should not be viewed as a design tool to be used when developing new code. They should be used solely for their intended purpose, which is language and platform RTL binding. type TMyClass = class procedure MyProc; function MyFunc: Integer; end; procedure TMyClass.MyProc; var X: Integer; begin X := MyFunc; end; function TMyClass.MyFunc: Integer; begin end; type TMyClassHelper = class helper for TMyClass procedure HelloWorld; function MyFunc: Integer; end; ... procedure TMyClassHelper.HelloWorld; begin WriteLn(Self.ClassName); // Self refers to TMyClass type, not TMyClassHelper end; function TMyClassHelper.MyFunc: Integer; begin ... end; var X: TMyClass; begin X := TMyClass.Create; X.MyProc; // Calls TMyClass.MyProc X.HelloWorld; // Calls TMyClassHelper.HelloWorld X.MyFunc; // Calls TMyClassHelper.MyFunc end; Strict private/protected A member of a class declared with the strict private visibility is accessible only within the class in which it is declared - not visible to procedures or functions declared within the same unit. A member of a class declared with the strict protected visibility is accessible within the class in which it is declared, and within any descendant class. Here's an example: type TMyClass = Class strict private procedure StrictPrivateProcedure; strict protected procedure StrictProtectedProcedure; public procedure PublicProceudre; End; TMyOtherClassClass = class(TMyClass) public procedure OtherPublicProceudre; end; { TMyClass } procedure TMyClass.StrictPrivateProcedure; begin end; procedure TMyClass.StrictProtectedProcedure; begin end; procedure TMyClass.PublicProceudre; begin end; { TMyOtherClassClass } procedure TMyOtherClassClass.OtherPublicProceudre; begin StrictProtectedProcedure; StrictPrivateProcedure; end; This example will actually not compile because TMyOtherClassClass.OtherPublicProceudre are tyring to access TMyClass.StrictPrivateProcedure; [Pascal Error] Unit1.pas(352): E2003 Undeclared identifier: 'StrictPrivateProcedure' Records with Methods In addition to fields, records now may have properties and methods (including constructors), class properties, class methods, class fields, and nested types. The rule is that you can add only non-virtual methods, as records inheritance is not supported in Win32. You can also define a pseudo-constructor to initialize the data, but you cannot have a destructor. The key difference between records and classes is the way they are allocated in memory. Variables having a class as type are allocated dynamically: in this case a variable is a reference to the actual memory location of the object. Variables with a record as type are allocated locally, either on the stack (for local method variables), within the containing object (for class fields), or in the global memory (for global variables). The differences in memory allocation can cause some significant differences in the processing time (generally favoring records) and in the amount of memory used (often favoring classes). Class Declaring Nested Types The nestedTypeDeclaration follows the type declaration syntax defined in Declaring Types . type className = class [abstract | sealed] (ancestorType) memberList type nestedTypeDeclaration memberList end; Nested type declarations are terminated by the first occurance of a non-identifier token, for example, procedure, class, type, and all visibility scope specifiers. The normal accessibility rules apply to nested types and their containing types. A nested type can access an instance variable (field, property, or method) of its container class, but it must have an object reference to do so. A nested type can access class fields, class properties, and class static methods without an object reference, but the normal Delphi visibility rules apply. Nested types do not increase the size of the containing class. Creating an instance of the containing class does not also create an instance of a nested type. Nested types are associated with their containing classes only by the context of their declaration. An syntax example : type TClassName = class public Procedure P1; Procedure P2; type MyNestedTypeDeclaration = Integer; private procedure p3(a : MyNestedTypeDeclaration); procedure P4; end; Nested Classes The following example demonstrates how to declare and access fields and methods of a nested class. type TOuterClass = class strict private myField: Integer; public type TInnerClass = class public myInnerField: Integer; procedure innerProc; end; procedure outerProc; end; To implement the innerProc method of the inner class, you must qualify its name with the name of the outer class. For example procedure TOuterClass.TInnerClass.innerProc; begin ... end; To access the members of the nested type, use dotted notation as with regular class member access. For example var x: TOuterClass; y: TOuterClass.TInnerClass; begin x := TOuterClass.Create; x.outerProc; ... y := TOuterClass.TInnerClass.Create; y.innerProc; end; Nested Constants Constants can be declared in class types in the same manner as nested type sections. Constant sections are terminated by the same tokens as nested type sections, specifically, reserved words or visibility specifiers. Typed constants are not supported, so you cannot declare nested constants of value types, such as Borland.Delphi.System.Currency , or Borland.Delphi.System.TDateTime . Nested constants can be of any simple type: ordinal, ordinal subranges, enums, strings, and real types. The following code demonstrates the declaration of nested constants: type TMyClass = class const x = 12; y = TMyClass.x + 23; procedure Hello; private const s = 'A string constant'; end; begin writeln(TMyClass.y); // Writes the value of y, 35. end. Class var A class can also have a class variable, applicable only to the class and not an instance of the class. type TClassWithClassType = class private type TRecordWithinAClass = record SomeField: string; end; public class var RecordWithinAClass: TRecordWithinAClass; end; ... procedure TForm1.FormCreate(Sender: TObject); begin TClassWithClassType.RecordWithinAClass.SomeField := 'This is a field of a class type declaration'; ShowMessage(TClassWithClassType.RecordWithinAClass.SomeField); end; Final methods A virtual method that you override can now be marked final, preventing derived classes from overriding that method TAbstractClass = classabstract public procedure Bar; virtual; end; TSealedClass = classsealed(TAbstractClass) public procedure Bar; override; end; TFinalMethodClass = class(TAbstractClass) public procedure Bar; override; final; end; Sealed methods Classes marked as sealed cannot be descended from. See the example in 'final methods' Static class methods Classes can have static class methods -- i.e. methods that can be called from a class type. Class static methods can be accessed without an object reference. Unlike ordinary class methods, class static methods have no Self parameter at all. They also cannot access any instance members. (They still have access to class fields, class properties, and class methods.) Also unlike class methods, class static methods cannot be declared virtual. type TMyClass = class strict private class var FX: Integer; strict protected // Note: accessors for class properties must be declared class static. class function GetX: Integer; static; class procedure SetX(val: Integer); static; public class property X: Integer read GetX write SetX; class procedure StatProc(s: String); static; end; TMyClass.X := 17; TMyClass.StatProc('Hello'); for-in loop Delphi 2007 for Win32 supports for-element-in-collection style iteration over containers. The following container iteration patterns are recognized by the compiler: for Element in ArrayExpr do Stmt; for Element in StringExpr do Stmt; for Element in SetExpr do Stmt; for Element in CollectionExpr do Stmt; Localized char-set You can now use the special characters of you own language for class names methods etc, even tough the code completion have some problems with it. For example Im Danish. The Danish word for donkey are sel so instead of TDonkey I can write : Type Tsel = class public Procedure p1; end; But code completion is not prepared for it so you would have to correct it by hand. Credits: Parts of this article was wrote by Nick Hodges in the site codegear.com If you like this article. please rate it.