Board index » delphi » Circular unit reference - how to solve

Circular unit reference - how to solve

I have problems with circular unit references in Delphi and
I dont know how tol solve it out. Perhaps someone have a trick
or tips for this, I have already looked for it at Borland and some
other WWW-sites and in the newsgroups but I haven't find a solution,
maybe there are no solution.

THE PROBLEM
I have two classes that have references to each other and
I want to save them in separate files. The files look like
this,

unit unitA;
uses
        unitB;
type
        TClassA=class
                b:TClassB;
        end;
implementaion
etc...

unit unitB;
uses
        unitA;
type
        TClassB=class
                a:TClassA;
        end;

and of course I got a circular unit reference error, is there  
a way to go around this.

Regards

Ulf Mansson
--

Ulf Mansson, Systems Management at Chalmers Univ. of Technology
ma...@mot.chalmers.se  Ph: +46 31 7725280, 7722497(fax)
Snail: Chalmers Univ. of Tech., S-412 96 Goteborg, Sweden

 

Re:Circular unit reference - how to solve


Quote
Duncan Murdoch (dmurd...@mast.queensu.ca) wrote:

: In article <4174b4$...@nyheter.chalmers.se> d8ma...@dtek.chalmers.se (Ulf Maansson) writes:

: >THE PROBLEM
: >I have two classes that have references to each other and
: >I want to save them in separate files. The files look like
: >this,

: >unit unitA;
  { Get rid of this here
: >uses
: >        unitB;
  }
: >type
: >        TClassA=class
: >                b:TClassB;
: >        end;
: >implementaion

   { put it here }
  uses UNITB;

In other words just move the uses clause to the implementation section.

--
Al Lipscomb AA4YU | The real question is: do you want  | System Programmer
a...@intnet.net    | to help, or do you want to pay     | All opinions are
St. Pete, FL      | someone to help?                   | my own.

Re:Circular unit reference - how to solve


Quote
In article <4174b4$...@nyheter.chalmers.se> d8ma...@dtek.chalmers.se (Ulf Maansson) writes:
>THE PROBLEM
>I have two classes that have references to each other and
>I want to save them in separate files. The files look like
>this,
>unit unitA;
>uses
>        unitB;
>type
>        TClassA=class
>                b:TClassB;
>        end;
>implementaion

... and the unitB interface was similar.  

You can't have these in separate units, but there's nothing to stop you from
putting them in different files that are included in the same unit.  I'd
suggest putting the interface section in one file, and the two implementations
in separate include files.

Duncan Murdoch

Re:Circular unit reference - how to solve


In <4174b4$...@nyheter.chalmers.se>, d8ma...@dtek.chalmers.se (Ulf Maansson) writes:
Quote
>I have problems with circular unit references in Delphi and
>I dont know how tol solve it out. Perhaps someone have a trick
>or tips for this, I have already looked for it at Borland and some
>other WWW-sites and in the newsgroups but I haven't find a solution,
>maybe there are no solution.

>THE PROBLEM
>I have two classes that have references to each other and
>I want to save them in separate files. The files look like
>this,

>unit unitA;
>uses
>    unitB;
>type
>    TClassA=class
>            b:TClassB;
>    end;
>implementaion
>etc...

>unit unitB;
>uses
>    unitA;
>type
>    TClassB=class
>            a:TClassA;
>    end;

>and of course I got a circular unit reference error, is there  
>a way to go around this.

>Regards

>Ulf Mansson
>--

In BP7 you solve this writing the USES clause in the IMPLEMENTATION instead
of in the INTERFACE part of the unit. In Delphi it will be the same I guess.

Re:Circular unit reference - how to solve


Quote
In article <4174b4$...@nyheter.chalmers.se>, d8ma...@dtek.chalmers.se (Ulf Maansson) writes:

|
| THE PROBLEM
| I have two classes that have references to each other and
| I want to save them in separate files. The files look like
| this,
|
| unit unitA;
| uses
|       unitB;
| type
|       TClassA=class
|               b:TClassB;
|       end;
| implementaion
| etc...
|
|
| unit unitB;
| uses
|       unitA;
| type
|       TClassB=class
|               a:TClassA;
|       end;
|
| and of course I got a circular unit reference error, is there  
| a way to go around this.

  There is a standard trick for this kind of situation: Say unit B is logically
  the one that should depend on A. Then you make a new class TSuperB which is
  included in unit A. It should look like this:

  TSuperB=class
    <The harmless attributes needed in this unit>

    <Methods needed in this unit, declared as virtual with empty bodies, to be
     filled out in unit B.>
  END;

  And then you make TClassB a subclass of TSuperB. This won't always work, but
  it solves most problems of this kind. The key is the virtual methods.

  --Lars M.
_______________________________________________________________________________

  -- Lars M. Garshol, Institute of Informatics, Oslo University

     "Life is a {*word*225}ly transmitted disease." -- A. Brink
     http://www.ifi.uio.no/~larsga

Re:Circular unit reference - how to solve


You need to do something like this:

unit unitA;
uses
        unitB;
type
        TClassA=class
                b:TClassB;
        end;
implementaion
etc...

unit unitB;
type
        TClassB=class
                a:TClassA;

implementation
uses
        unitA;
etc...

Good Luck,

Don Huff
dh...@sky.net

Quote
Ulf Maansson (d8ma...@dtek.chalmers.se) wrote:

: I have problems with circular unit references in Delphi and
: I dont know how tol solve it out. Perhaps someone have a trick
: or tips for this, I have already looked for it at Borland and some
: other WWW-sites and in the newsgroups but I haven't find a solution,
: maybe there are no solution.

: THE PROBLEM
: I have two classes that have references to each other and
: I want to save them in separate files. The files look like
: this,

: unit unitA;
: uses
:       unitB;
: type
:       TClassA=class
:               b:TClassB;
:       end;
: implementaion
: etc...

: unit unitB;
: uses
:       unitA;
: type
:       TClassB=class
:               a:TClassA;
:       end;

: and of course I got a circular unit reference error, is there  
: a way to go around this.

: Regards

: Ulf Mansson
: --

: Ulf Mansson, Systems Management at Chalmers Univ. of Technology
: ma...@mot.chalmers.se  Ph: +46 31 7725280, 7722497(fax)
: Snail: Chalmers Univ. of Tech., S-412 96 Goteborg, Sweden

Re:Circular unit reference - how to solve


Quote
wcle...@ibm.net wrote:

> In <4174b4$...@nyheter.chalmers.se>, d8ma...@dtek.chalmers.se (Ulf Maansson) writes:
> >I have problems with circular unit references in Delphi and
> >I dont know how tol solve it out. Perhaps someone have a trick
> >or tips for this, I have already looked for it at Borland and some
> >other WWW-sites and in the newsgroups but I haven't find a solution,
> >maybe there are no solution.

> >THE PROBLEM
> >I have two classes that have references to each other and
> >I want to save them in separate files. The files look like
> >this,

> >unit unitA;
> >uses
> >       unitB;
> >type
> >       TClassA=class
> >               b:TClassB;
> >       end;
> >implementaion
> >etc...

> >unit unitB;
> >uses
> >       unitA;
> >type
> >       TClassB=class
> >               a:TClassA;
> >       end;

> >and of course I got a circular unit reference error, is there  
> >a way to go around this.

> >Regards

> >Ulf Mansson
> >--

> In BP7 you solve this writing the USES clause in the IMPLEMENTATION instead
> of in the INTERFACE part of the unit. In Delphi it will be the same I guess.

This trick only works when you only refer to the other units' class
in the IMPLEMENTATION part. When you want your unit to 'export' this
particular class you can use this trick (which works in BP7):

unitA

type
  PClassA=^TClassA (a pointer to types of TClassA)
  TClassA=class
         b : pointer (general pointer, because TClassB is not known yet)
  end;

implementation

uses
  UnitB
  etc....

unitB

uses
  UnitA (No circular references...)

type
  PClassB=^TClassB (a pointer to type of TClassB)
  TClassB=class
        a : PClassA (or TClassA, I prefer the first for consistancy)
  end;

implementation
etc...

To acces the b field in TClassA records as an instance of type TClassB
you'll have to do the following:

  PClassB(b)^ (this is called typecasting)

I hope this solves your problem.

Harold Veelenturf
CombiR...@box.nl

Re:Circular unit reference - how to solve


Quote
In article <dmurdoch.2752.3037D...@mast.queensu.ca> dmurd...@mast.queensu.ca (Duncan Murdoch) writes:
>From: dmurd...@mast.queensu.ca (Duncan Murdoch)
>Subject: Re: Circular unit reference - how to solve
>Date: Mon, 21 Aug 1995 01:14:05 GMT
>In article <4174b4$...@nyheter.chalmers.se> d8ma...@dtek.chalmers.se (Ulf
>Maansson) writes:
>>THE PROBLEM
>>I have two classes that have references to each other and
>>I want to save them in separate files. The files look like
>>this,
>>unit unitA;
>>uses
>>        unitB;
>>type
>>        TClassA=class
>>                b:TClassB;
>>        end;
>>implementaion

>... and the unitB interface was similar.  
>You can't have these in separate units, but there's nothing to stop you from
>putting them in different files that are included in the same unit.  I'd
>suggest putting the interface section in one file, and the two implementations
>in separate include files.
>Duncan Murdoch

To avoid the circular reference problem;

Place the first use clause in the interface part of Unit A

Quote
>unit unitA;

>interface

>uses
>    unitB;

>implementation

In unit B place the use clause for unitA in the implementation part.

- Show quoted text -

Quote
>unit unitB;

>interface

>uses
>    whatever;

>implementation
>uses
>    unitA;

Re:Circular unit reference - how to solve


Quote
In article <johnsylv.5.00138...@InterLink.Net> johns...@InterLink.Net (John Sylvestre) writes:
>>>unit unitA;
>>>uses
>>>        unitB;
>>>type
>>>        TClassA=class
>>>                b:TClassB;
>>>        end;
>>>implementaion

>>... and the unitB interface was similar.  
>To avoid the circular reference problem;
>Place the first use clause in the interface part of Unit A ...
>In unit B place the use clause for unitA in the implementation part.

This doesn't work, because unitA is needed in the interface to unitB in order
to resolve the meaning of  a TClassA typed field declared there.  (I deleted
this in the extract I quoted above.)  Someone else worked around this by
changing one of the type declarations to an untyped pointer and then
typecasting it, and another solution was to declare an ancestor type somewhere
else and have each unit use that instead.

I still think the best solution is to put both classes in the same unit,
possibly in separate include files.  These two classes must be intimately
related if they use each other so closely, so it makes sense for them to be
logically grouped together.  

A valid reason to employ one of these kludges to get them into separate units
would be if the implementations involved so much code that it wouldn't all fit
into one unit.  In that case, it would probably make sense to have multiple
types in a hierarchy anyways; I don't think I've ever needed 64K of code to
implement just two object types.

Duncan Murdoch

Re:Circular unit reference - how to solve


Quote
Ulf Maansson (d8ma...@dtek.chalmers.se) wrote:
> THE PROBLEM
> I have two classes that have references to each other and
> I want to save them in separate files. The files look like
> this,

...

If they have references to each other, their definitions should be in
one file. Just create a unitC which contains the typedefs in the interface
section. Then you can use unitC in unitA & unitB.
  Circular references are a sign of bad decomposition. Please look very
careful at your interface sections.

Stephan

Re:Circular unit reference - how to solve


Quote
dmurd...@mast.queensu.ca (Duncan Murdoch) writes:
>In article <johnsylv.5.00138...@InterLink.Net> johns...@InterLink.Net (John Sylvestre) writes:

Thanks for all responses on my question.

Quote
>>To avoid the circular reference problem;
>>Place the first use clause in the interface part of Unit A ...
>>In unit B place the use clause for unitA in the implementation part.
>This doesn't work, because unitA is needed in the interface to unitB in order
>to resolve the meaning of  a TClassA typed field declared there.  (I deleted
>this in the extract I quoted above.)  Someone else worked around this by
>changing one of the type declarations to an untyped pointer and then
>typecasting it, and another solution was to declare an ancestor type somewhere
>else and have each unit use that instead.

This is correct. It wouldn't work for me to move the unit declaration to the
implementaion part of unit b. The pointer soultion would work but
it would make the code look more hard to read and manage, it would be a
last resort for me.

Quote
>I still think the best solution is to put both classes in the same unit,
>possibly in separate include files.  These two classes must be intimately
>related if they use each other so closely, so it makes sense for them to be
>logically grouped together.  

Yes,  they are intimately related but I would have liked to have them in two
separate units, but it doesn't look like it can be made. I think I will go for
joining the two classes in one file or make two separate include files.

Quote
>A valid reason to employ one of these kludges to get them into separate units
>would be if the implementations involved so much code that it wouldn't all fit
>into one unit.  In that case, it would probably make sense to have multiple
>types in a hierarchy anyways; I don't think I've ever needed 64K of code to
>implement just two object types.

The classes are not that huge, but I like the concept of having one class in
one unit. In this case it doesn't seams like it's possible.

/Ulf Mansson
--

Ulf Mansson, Systems Management at Chalmers Univ. of Technology
ma...@mot.chalmers.se  Ph: +46 31 7725280, 7722497(fax)
Snail: Chalmers Univ. of Tech., S-412 96 Goteborg, Sweden

Re:Circular unit reference - how to solve


Quote
Ulf Maansson (d8ma...@dtek.chalmers.se) wrote:
> THE PROBLEM
> I have two classes that have references to each other and
> I want to save them in separate files. The files look like
> this,

...

If they have references to each other, their definitions should be in
one file. Just create a unitC which contains the typedefs in the interface
section. Then you can use unitC in unitA & unitB.
  Circular references are a sign of bad decomposition. Please look very
careful at your interface sections.

Stephan

Re:Circular unit reference - how to solve


Quote
dmurd...@mast.queensu.ca (Duncan Murdoch) writes:
>In article <johnsylv.5.00138...@InterLink.Net> johns...@InterLink.Net (John Sylvestre) writes:

Thanks for all responses on my question.

Quote
>>To avoid the circular reference problem;
>>Place the first use clause in the interface part of Unit A ...
>>In unit B place the use clause for unitA in the implementation part.
>This doesn't work, because unitA is needed in the interface to unitB in order
>to resolve the meaning of  a TClassA typed field declared there.  (I deleted
>this in the extract I quoted above.)  Someone else worked around this by
>changing one of the type declarations to an untyped pointer and then
>typecasting it, and another solution was to declare an ancestor type somewhere
>else and have each unit use that instead.

This is correct. It wouldn't work for me to move the unit declaration to the
implementaion part of unit b. The pointer soultion would work but
it would make the code look more hard to read and manage, it would be a
last resort for me.

Quote
>I still think the best solution is to put both classes in the same unit,
>possibly in separate include files.  These two classes must be intimately
>related if they use each other so closely, so it makes sense for them to be
>logically grouped together.  

Yes,  they are intimately related but I would have liked to have them in two
separate units, but it doesn't look like it can be made. I think I will go for
joining the two classes in one file or make two separate include files.

Quote
>A valid reason to employ one of these kludges to get them into separate units
>would be if the implementations involved so much code that it wouldn't all fit
>into one unit.  In that case, it would probably make sense to have multiple
>types in a hierarchy anyways; I don't think I've ever needed 64K of code to
>implement just two object types.

The classes are not that huge, but I like the concept of having one class in
one unit. In this case it doesn't seams like it's possible.

/Ulf Mansson
--

Ulf Mansson, Systems Management at Chalmers Univ. of Technology
ma...@mot.chalmers.se  Ph: +46 31 7725280, 7722497(fax)
Snail: Chalmers Univ. of Tech., S-412 96 Goteborg, Sweden

Re:Circular unit reference - how to solve


Quote
step...@stack.urc.tue.nl (Stephan Eggermont) wrote:

[snip]
Quote
>  Circular references are a sign of bad decomposition. Please look very

                       ^^^
I think you misspelled "can be" :-)

Quote
>careful at your interface sections.

>Stephan

-----------------------------------
Matt Francomb, Setanta Software Ltd
http://www.demon.co.uk/setanta
-----------------------------------

Re:Circular unit reference - how to solve


In article <418quj$...@mack.rt66.com>, jre...@rt66.com says:

Quote
>>  THE PROBLEM
>>  I have two classes that have references to each other and
>>  I want to save them in separate files. The files look like
>>  this,

>[snip]

>Put at least one of your uses clauses in the implementation section instead.

>John

The answer is right. It might happen with three or more units: unit a USES
unit b, which USES unit c, which in turn USES unit a.
If all the USES clauses are in the respective Interface sections, you are
in trouble. The rule, as I reckon, is that each circular reference of
any length must be broken by putting one of the USES in the Implementation
section.

I hope this clears things up.

Andrea Damiani (mc2...@mclink.it)

Other Threads