Thursday, November 23, 2006

DN4DP#3: Nesting habits

This post continues the series of The Delphi Language Chapter teasers from Jon Shemitz’ .NET 2.0 for Delphi Programmers book. Last time we learned about the new class member visibility specifiers that are available, abstract classes and final methods. This time we will look at the syntax and semantics of nested classes.

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.

"Nesting habits

The compiler now allows you to declare nested types (including classes) and constants inside another class or record declaration. The implementation of a nested class method must have its name preceded by both the outer and inner class names, like this

type
TOuter = class
public
const
MeaningOfLife = 42;
type
TResult = integer;
TInner = class
public
function Method: TResult;
end;
end;

implementation

function TOuter.TInner.Method;
begin
// or just MeaningOfLife

Result := TOuter.MeaningOfLife;
end;

procedure Test;
var
Inner: TOuter.TInner;
Result: TOuter.TResult;
begin
Inner := TOuter.TInner.Create;
Result := Inner.Method;
end;

Note that a nested class can reference all types and constants nested within its parent class – the TOuter prefix in the above example is optional. Any code outside of a class must use an explicit type prefix – for example, the external test code in the Chapter10\NestingHabits project must use the TOuter prefix to get at the types and constants declared in the TOuter class.

Remember, while inner classes can see all types declared in their outer class(es), they have no special access to their outer class’ fields, methods, or properties. (Similarly, outer classes cannot see private or protected members of their inner types). The main purpose of nested classes is to reduce namespace clutter by keeping (often private) helper classes within the public classes that use them. This also makes it easier to hide implementation details. (See Chapter 2’s Nested Classes section.)

Tip   Delphi’s global level constants are not CLS-compliant (or rather, the name of the class they end up in is an implementation detail generated by the compiler, and should not be relied upon), so you should declare constants you want to export to other languages inside a class or record declaration. The same advice goes for global routines and variables - declare them as static methods and fields."

1 comment:

Anonymous said...

Normally, I prefer Delphi's seperate declaration and implementation for its clean-ness compared to C++,C#, Java etc's code in place.

This is one place, however that the C-ish code in place model is definitely cleaner.

I am finding that with collapse to definitions that C# is gaining back any ground left to seperate declaration and implementation as you can quickly collapse to just declarations. Delphi's implementation doesn't seem to function quite as cleanly.



Copyright © 2004-2007 by Hallvard Vassbotn