Solving circular unit references with class helpers

Thursday, June 9th, 2011 | Dennis D. Spreen | Delphi 2009, Delphi 2010, Delphi Programming, Delphi XE

Sooner or later you run into the circular unit reference problem when using a single unit for each class. There are some solutions (move the common used structs into a separate unit, use type casting, redesign your obvious bad class design, etc.) – this is a solution using class helpers. Recommended reading: “Class Helpers – good or bad ?” and “New Delphi language features since Delphi 7“:

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

Let’s suppose we have a simple TDog class:

and a corresponding TMaster class:

Let’s create our objects:

Works. Now we’re adding the dog’s master in our TDog class:

Ok, compiles. Alright. Now what if we need a reference to our dog in the TMaster class? First approach:

Won’t compile – circular unit reference (unit Dog uses unit Master, and unit Master uses unit Dog). You may getting around by using TObject as the Dog object:

Well, that compiles – but you always have to type cast your Dog object:

Now – how about using class helpers? First we move the Dog object into our protected area:

then we introduce a new class helper which “exports” the dog as a TDog class

Now we’re able to access the Dog reference of the Master object without typecasting:

Adding the MasterClassHelper in the implementation part of the Master unit allows us to access the TDog class inside our TMaster class, too:

Download Delphi source DogMaster.zip

Tags:

10 Comments to Solving circular unit references with class helpers

Stefan Glienke
June 10, 2011

It’s really time to enhance the helpers in delphi to make them work more like c# extensions (i.e. allowing helpers to more than records and classes and, being able to use more than one helper)
I also use class helpers at some places in my own projects but most of the times it kinda smells bad imo.

Antonio
June 10, 2011

@Stefan, I agree that class helpers needs enhanctmens but it’s far more important that Delphi finally gets proper namespaces instead of units

Dennis
June 10, 2011

+1 for proper namespace, too. Allowing usage of multiple class helpers shouldn’t be that “compiler complicated” either I’ll guess…

Marcus
June 10, 2011

There’s really no excuse to have to hack together workarounds for something that the compiler should be doing itself. I understand the single-pass concept in the compiler, which I’m sure was wonderful back when source code was kept on floppy disks. But there’s really no excuse for it to not be able to resolve circular references itself now.

Marjan
June 11, 2011

@Marcus: The speed of a single pass compiler is still very important. Even with high speed HDD’s. I would get very very impatient if a 1M LOC project would take more than a minute to compile… Fast compiles are an essential requirement for my TDD routine and I couldn’t get anywhere near as efficient with a multi-pass compiler. I’ll more than happily take having to fix circular dependencies if that means the compiler will stay single pass…

Dennis
June 14, 2011

If the compiler runs into a circular reference, why not adding a second pass just for these units?

Mason Wheeler
June 20, 2011

…or you could just group related classes together in the same unit, the way Delphi developers have been doing since the very beginning, instead of trying to shoehorn a silly Java concept like “one class per file” into a language that doesn’t use Java’s object model. ๐Ÿ˜›

Jeroen Pluimers
June 20, 2011

It is really time that C# adds some of the strengths (property helpers anyone?) of Delphi class helpers.

Dennis
June 22, 2011

@mason:
I really like the “one class per file” java paradigm – it helps to reduce writing monster units. And it’s somewhat easier to write code with many developers involved.
IMHO if your class needs code (so it’s not a “data class”) it should be in a separate unit.
Therefore I’ll vote for a

“uses Classes, Generics.*, MyCrypt.*, Gui.Login.*;”

uses declaration (java inspired of course)

Tony
September 20, 2011

This looks like it could be very useful.. we started using base classes to help with the type safety, but automatic casting would simplify a lot of code.

As far as ‘all classes in one file’ goes – We have individual source files over 50,000 lines long because a previous developer thought like that and are having to break everything down again just to stop the delphi compiler falling over so often (it does *not* like large files). It’s also a code maintainability nightmare.

Leave a comment

About Dennis D. Spreen

I'm an avid programmer working on a variety of platforms in a variety of languages with a wide technical interest.

Search

QR Code

Categories