Frank Heckenbach wrote:
Gale Paeper wrote:
[snip]
The forward object type declaration must have a complete type declaration in the same type declaration part (like Pascal's requirement for pointer types). The commented out var declaration part and type keyword is what I used to test that requirement. Uncomment that part and you get:
Error : unresolved forward class reference to 'objA' ForwardObjectTest.p line 11 var
Good (in accordance with OOE, except for the syntax).
The other part of OOE's deferred class requirement (i.e., "cannot be used in a class-inheritance-list before its complete definition is specified") is also enforced. A slight modification of the test program I've been using for an example:
program ForwardObjectTest1;
type objA = object; forward; objB = object {...} o : objA; { objB uses objA } {...} end;
{ WRONG - Can't inherit from a FORWARD declared object } { objC = object(objA)
end; } objA = object {...} p : objB; { objB uses objA } {...} end;
{ OK - Can inherit from a FORWARD object after it is fully defined } objD = object(objA) { objD inherits from objA } end;
begin end.
With the objC type declaration commented out the program compiles without error. Uncomment the objC type declaration and you get the follow compilation error with CodeWarrior Pascal:
Error : class 'objA' was declared 'FORWARD' or 'EXTERNAL' ForwardObjectTest1.p line 12 objC = object(objA)
For the sake of completeness and since the error message refers to external object declarations, I suppose CodeWarrior Pascal and MPW Pascal's support for external object declarations should be mentioned.
The basic purpose and reason for external object declaration is the same as it is for forward declared objects except it is used for mutually dependent object type declarations between unit interfaces.
Before an example program demonstrating the external object feature and how it can be used, a few notes on this particular MacPascal Object Pascal feature:
1. I'm not sure any real world program actually makes use of it.
2. Even Apple, who invented the feature for MPW Pascal, called code using external objects "ugly" and the code, even though it maybe useful, confusing.
3. It isn't the easiest feature to make use of. It takes some thought and care in organizing code to avoid circular unit interface dependency errors and unresolved external object declaration errors.
So, there's no misunderstanding, I'm not asking for GPC's support for MacPascal style objects to include external object declaration support. Put it in the "to be considered if someone really needs it" bin. I'm covering MacPascal external object declaration support so that Frank and Waldek are at least aware of the feature and have an example of its usage.
The example program and units are:
program ExternalObjectTest;
uses UObjA, UObjB; var ObjAInstance: ObjA; ObjBInstance: ObjB;
begin ObjAInstance := NewObjA; ObjBInstance := NewObjB; ObjAInstance.InitwithObjB(ObjBInstance); ObjBInstance.InitwithObjA(ObjAInstance); ObjAInstance.TestObjAsObjBReference; ObjBInstance.TestObjBsObjAReference; Dispose(ObjAInstance); Dispose(ObjBInstance); end.
unit UObjA;
interface
type ObjB = object; external; ObjA = object fObjB: ObjB; procedure InitwithObjB(InitObj: ObjB); procedure TestObjAsObjBReference; procedure TestIt; end;
function NewObjA: ObjA;
implementation
uses UObjB;
function NewObjA: ObjA; var obj: ObjA; begin new(obj); NewObjA := obj; end;
procedure ObjA.InitwithObjB(InitObj: ObjB); begin fObjB := InitObj; end;
procedure ObjA.TestObjAsObjBReference; begin writeln ('In ObjA calling fObjB'); fObjB.TestIt; end;
procedure ObjA.TestIt; begin writeln ('In ObjA TestIt'); end;
end.
unit UObjB;
interface
uses UObjA; type ObjA = object; external; ObjB = object fObjA: ObjA; procedure InitwithObjA(InitObj: ObjA); procedure TestObjBsObjAReference; procedure TestIt; end;
function NewObjB: ObjB;
implementation
function NewObjB: ObjB; var obj: ObjB; begin new(obj); NewObjB := obj; end;
procedure ObjB.InitwithObjA(InitObj: ObjA); begin fObjA := InitObj; end;
procedure ObjB.TestObjBsObjAReference; begin writeln ('In ObjB calling fObjA'); fObjA.TestIt; end;
procedure ObjB.TestIt; begin writeln ('In ObjB TestIt'); end;
end.
When compiled with CodeWarrior Pascal and subsequently ran, the program output is:
In ObjA calling fObjB In ObjB TestIt In ObjB calling fObjA In ObjA TestIt
Gale Paeper gpaeper@empirenet.com