Graeme Geldenhuys wrote:
Lance posted this in the Lazarus mailing list, and I think it is more
appropriate here...
Lance Collins wrote:
>> How can you avoid circular references with two modules that
>> interact with each other?
Basically it should be possible with a minor language change and not too
much effort from the compiler team. Something like:
unit ParentObject;
interface
TChild = forward class; // My made-up syntax
// or TChild = implementation class; or some other syntax!
TParent = Class
public
property Child :TChild;
end;
implementation
uses ChildObject;
// Nothing special here, only need the love one-way
// but you could do it both ways if you want
unit ChildObject;
interface
uses ParentObject;
TChild = Class
public
property Parent :TParent;
end;
"TChild = forward class" tells the compiler that TChild is a class,
and the
complete type information is known in the implementation section
(which the
compiler can validate).
> This feature is often needed and the "if you need to do that then
> something is wrong with your design" argument doesn't fly with me.
I can't agree more. Sometimes there is a valid design for something
like that. The compilers already handle forward declarations in the
same unit, so why can that not be applied for multiple units as well.
And if the forward declaration is not fully resolved by the time the
whole project or unit is compiled - raise a compiler error.
The current usage of forward declaration is exactly the same principle
we are trying to use, but this time just across units. Why can't the
FPC compiler maybe in ObjFPC mode cater for this?
I posted a similar (probable) explanation/problem resulting from this,
but it is better explained on the example above.
unit Foo;
uses ParentObject;
....
implementation
procedure Bar(parent: TParent );
begin
parent.Child := TListBox.Create(nil);
end;
because unit ParentObject does not say in it's interface what exactly
Child can be (except it must be some instance of some class (in other
words any object) , the compiler can not decide if the code about is
correct or not.
You either loose the strong typed structure of pascal, or the compiler
has to read the implementation of ParentObject in advance, which looses
the benefit of differing between interface and implementation. Because
now circular references in the implementation can no longer be resolved
by knowing the interfaces (as we just discovered, that interfaces became
useless without implementation). This means that it will ultimately mean
multiply passes in order to compile......
Martin
_______________________________________________
fpc-devel maillist - fpc-devel@lists.freepascal.org
http://lists.freepascal.org/mailman/listinfo/fpc-devel