Saturday, September 22, 2007

DN4DP#17: .NET only: Multi-unit namespaces

This post continues the series of The Delphi Language Chapter teasers from Jon Shemitz’ .NET 2.0 for Delphi Programmers book.

The previous post covered platform differences for floating-point semantics. This time we'll look at namespace support.

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.

"Multi-unit namespaces

With the trinity of a logical unit concept, physical unit source .pas files and compiled .dcu files, Delphi has always had a very efficient and useful module concept. To address the hierarchal namespace support required in .NET while still being backwards compatible, Delphi 8 introduced the concept of dotted unit names, such as Borland.Vcl.SysUtils and Borland.Vcl.Classes - these unit names were mapped directly to .NET namespaces.

This was a step in the right direction, but Delphi 2005 extended this concept to allow multiple Delphi units to contribute to the same logical namespace. Now the namespace of a dotted unit name is everything up to the last dot.

So now both the SysUtils and Classes units reside in a single Borland.Vcl namespace. This allows the programmer to split his code into multiple physical units, while exposing the contained classes in a single logical namespace. This makes it easier and more convenient to write assemblies that can be used by other languages (such as C#).

unit MultiUnit.Namespaces.Unit2;
...
class procedure TBar2.Foo;
begin
Writeln(TBar2.ClassInfo.ToString, '.Foo');
end;

The code above writes the fully qualified namespace of the TBar2 type, and the output is MultiUnit.Namespaces.TBar2.Foo in this case.

unit MultiUnit.Namespaces.Unit1;

interface

type
TBar1 = class
class procedure Foo; static;
end;

procedure Test;

implementation

class procedure TBar1.Foo;
begin
{$IFDEF CLR}
Writeln(TBar1.ClassInfo.ToString, '.Foo');
{$ELSE}
Writeln(TBar1.ClassName, '.Foo');
{$ENDIF}
end;

procedure Test;
begin
TBar1.Foo;
end;

end.
unit MultiUnit.Namespaces.Unit2;

interface

type
TBar2 = class
class procedure Foo; static;
end;

implementation

class procedure TBar2.Foo;
begin
Writeln(TBar2.ClassInfo.ToString, '.Foo');
end;

end.
unit MultiUnit.Namespaces.Unit3;

interface

procedure Test;

implementation

uses
MultiUnit.Namespaces.Unit1,
MultiUnit.Namespaces.Unit2;

procedure Test;
begin
Writeln('Note that even though TBar1 and TBar2 are in separate Delphi units');
Writeln('they reside in the same namespace (MultiUnit.Namespaces)');
TBar1.Foo;
TBar2.Foo;
end;

end.

"

No comments:

Post a Comment

Comments are moderated - spam and non-relevant links to will be deleted.