Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can't understand Delphi XE6 protected types

I create two units and put a first class into one of them:

  unit UBaseClass;

  interface

  type
    TBaseOuterClass = class
    protected type

      TBaseInnerClass = class
      public
      end;

    protected
      function GetInnerInstance: TBaseOuterClass.TBaseInnerClass; virtual;
    end;

  implementation

  { TBaseOuterClass }

  function TBaseOuterClass.GetInnerInstance: TBaseOuterClass.TBaseInnerClass;
  begin
  // doesn't matter
  end;

  end.

And I put a derived class into a second unit:

unit UDerClass;

interface

uses
  UBaseClass;

type
  TDerOuterClass = class(TBaseOuterClass)
  protected type

    TDerInnerClass = class(TBaseInnerClass)

    end;

  protected
    function GetInnerInstance: TBaseOuterClass.TBaseInnerClass; override;
  end;

implementation

{ TDerOuterClass }

function TDerOuterClass.GetInnerInstance: TBaseOuterClass.TBaseInnerClass;
begin

end;

end.

When I'm trying to compile I get

[dcc32 Error] UDerClass.pas(22): E2362 Cannot access protected symbol TBaseOuterClass.TBaseInnerClass

at the line function TDerOuterClass.GetInnerInstance: TBaseOuterClass.TBaseInnerClass;

I can't understand why TBaseOuterClass.TBaseInnerClass (as inner protected class) isn't accessible from TDerOuterClass (which is derived for TBaseOuterClass). What in this case are protected types actually for?

I haven't found any explanation for this at Nested Type Declarations topic. So are there any reasons for this behaviour?

It's also relevant to simple protected types like

protected type    
  TSimpleType = Integer;

I can't write a function in TDerOuterClass

protected    
  function GetValue: TSimpleType;

since I'll get a message

[dcc32 Error] UDerClass.pas(16): E2003 Undeclared identifier: 'TSimpleType'

like image 960
tikskit Avatar asked Nov 12 '16 02:11

tikskit


1 Answers

It looks like a bug. I would suggest to post it to the quality portal.

For now you could declare type alias to cheat the compiler (tested in XE7).

unit UDerClass;

interface

uses
  UBaseClass;

type
  TDerOuterClass = class(TBaseOuterClass)
  protected type
    TBaseInnerClass = TBaseOuterClass.TBaseInnerClass; // <= type alias to avoid compiler error

    TDerInnerClass = class(TBaseInnerClass)

    end;

  protected
    function GetInnerInstance: TBaseInnerClass; override;
  end;

implementation

{ TDerOuterClass }

function TDerOuterClass.GetInnerInstance: TBaseInnerClass;
begin
  Result := TDerInnerClass.Create;
end;

end.
like image 70
Max Abramovich Avatar answered Sep 22 '22 23:09

Max Abramovich