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."