Question

This is an Object Pascal, I'm wondering if is that possible somehow without messing around with outer instance pointer and passing it to inner.
What i want to do is gain full access to the outter (ClassOne) class using the inner ones methods. I've been trying:

{ this class should be able to access by all clases inside it }
ClassOne = class
    type
        { can be accessed by ClassThree, can access: ClassOne }
        ClassTwo = class
            type
                { can be accessed by / can access: ClassOne and ClassTwo }
                ClassThree = class 
                    public
                        procedure MethodOne();
                end;

            private
                FieldOne: Array[1 .. 10] of ClassThree;
                FieldTwo: integer;

            public
                procedure MethodOne();
        end;

    private
        FieldOne: Array[1 .. 5] of ClassTwo;
        FieldTwo: Byte;

    public
        procedure MethodOne(Something: Byte);
end;

Implementation:

procedure ClassOne.MethodOne(Something: Byte);
begin
    FieldTwo := Something;
end;    

procedure ClassOne.ClassTwo.MethodOne();
begin
    { does something but not important in this case }
end;

procedure ClassOne.ClassTwo.ClassThree.MethodOne();
begin
    { here i need the FieldTwo value of ClassOne of the current instance }
    ClassOne(self).FieldTwo; // Does not work
end;

Access:

var Test: ClassOne;

...

Test := ClassOne.Create();
Test.FieldOne[2] := ClassOne.ClassTwo.Create;
Test.FieldOne[2].FieldOne[5] := ClassOne.ClassTwo.ClassThree.Create;

Test.MethodOne(15);
Test.FieldOne[2].MethodOne();
Test.FieldOne[2].FieldOne[5].MethodOne();

Iterations and array sizes are just random examples.

I think in Java its something like OuterClass.self.OuterClassField; but this does not work here.
This can be done by passing the outer instance right after creation, i know that, but it makes many trouble with constructors and instances later.
How can i make it work like that ?

UPDATE
Maybe this needs to be done with ancestors ?
This one compiles but crashes right after calling constructor of ClassTwo or ClassThree, why ?

ClassOne = class
    type
        ClassTwo = class(ClassOne) { changed ancestor }
            type
                ClassThree = class(ClassTwo) { changed ancestor }
                    public
                        procedure MethodOne();
                end;

            private
                FieldOne: Array[1 .. 10] of ClassThree;
                FieldTwo: integer;

            public
                procedure MethodOne();
        end;

    private
        FieldOne: Array[1 .. 5] of ClassTwo;
        FieldTwo: Byte;

    public
        procedure MethodOne(Something: Byte);
end;
Was it helpful?

Solution

Okay, looks like there is only one way to do it right, by passing and instance of the outter class to an inner class.
the best place to do it is the inner class constructor.
This requires an additional field in every nested class, that holds an instance.
From this level you have Full access to the outter class ( even Strict Private fields ).
A simple example using the class structure from my post above:

Test := ClassOne.Create();

{ Test is a ClassTwo parent }
Test.FieldOne[2] := ClassOne.ClassTwo.Create(Test);

{ Test.FieldOne[2] is a ClassThree parent }
Test.FieldOne[2].FieldOne[5] := ClassOne.ClassTwo.ClassThree.Create(Test.FieldOne[2]);

Then, evey nested class needs a field, i.e called Parent:

{ ClassTwo }
Strict Private
    Parent: ClassOne;
    ...
    { ClassThree}
    Strict Private
        Parent: ClassTwo;

Usage:

Procedure ClassOne.ClassTwo.ClassThree.Test();
Begin
    { Access ClassOne FieldTwo from ClassThree }
    Parent.Parent.FieldTwo;
End;
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top