Thursday, August 31, 2006

DN4DP#1: Getting classy

As most of you will know by now, I was the tech editor of Jon Shemitz’ great .NET 2.0 for Delphi Programmers book and I wrote chapter 10 on The Delphi Language – covering what’s new in the language since Delphi 7. Jon has made one chapter available for download.

To give you some extra teasers from the book, I will in the coming months post a few excerpts of The Delphi Language chapter. Note that I do not get any royalties from the book and I highly recommend that you get your own copy – for instance at Amazon.

"Getting classy

The object model has been extended with static members; class static methods, class constructors, class var fields and class properties. For example, the AppendixDfn\ClassStatic project shows this

TFoo = class
strict private
class constructor Create;
class var FYank: integer;
class procedure SetYank(const Value: integer); static;
class procedure OldVirtualClassProcedure; virtual;
class procedure OldClassProcedure;
class function ClassStaticMethod: integer; static;
class property Yank: integer read FYank write SetYank;

Note that C#-style static methods must be declared as class procedure or class function with a static directive. The reason for this is historic; Delphi also supports class procedures that receive an extra implicit TClass parameter: a reference to the actual class type the call is made on. This can be used to invoke virtual class methods polymorphically, something that is not supported in C# or with the new class static methods in Delphi.

A class var declaration introduces a block of global-lifetime, class-scoped fields. Traditionally, Delphi programmers have used global variables in the implementation section of the unit for this purpose, but declaring class var fields directly in the class is undeniably much cleaner and clearer. Note that to be consistent, normal instance fields can now also optionally be declared in a var block.

The availability of class fields also opened the path for class properties[1]. These are declared like normal instance properties, but use a class property prefix. The read and write accessors can be class fields or class static methods (but not the older class methods).

Finally, a class’ single class constructor is guaranteed to run exactly once before any members of the class are referenced. It should be declared strict private[2] and cannot be referenced directly from user code[3] – it is always invoked by the CLR when it deems it necessary. Often, code in the initialization section of the unit would benefit from being moved to a class constructor – then you would not incur the overhead unless you actually use the class.

Tip Note that class constructors are not supported in Win32. To emulate a class constructor in Win32, put the code in a strict private class static method and call the method from the initialization section of the unit.

[1] In Delphi 7 and earlier, you could actually declare instance properties that referenced class methods as the read and write accessors, but this was a compiler quirk and didn’t actually work correctly at run-time (using the implicit Self: TClass parameter such as calling a virtual class method would crash, for instance). Also while Delphi 8 allowed you to declare class properties, there was no intuitive way of accessing them (you had to access them via an instance reference, not a class reference). This issue has been fixed in Delphi 2006.

[2] While Delphi 2006 does allow declaring non-private class constructors, you can’t call them and the generated IL declares them private anyway, so it is cleaner to declare them as such in the Delphi code as well.

[3] Hackers and compilers can ensure it has been called by using the RuntimeHelpers.RunClassConstructor method from the System.Runtime.CompilerServices namespace."

[Note: This text differs slightly from the final printed version]


Daniel "sakura" Wischnewski said...

Noted ;-)

But I've got the book anyway on my shelf. A "must have" for Delphi developers imo.

Anonymous said...

An extremely good book, and a great chapter on Delphi.

Copyright © 2004-2007 by Hallvard Vassbotn