是否可以使用在接口部分的实现部分中声明的类

如果我理解正确,该interface部分对其他单位可见,并且该implementation部分仅在当前.pas文件中可见。

我有两个类,类TA应该对外可见,其他类TB不应该,但我需要一个类型为TBin的字段TA

interface
    
type
  TA = class
    //something
    B : TB;
  end;
    
//something
    
implementation
    
type
  TB = class
    //something
  end;

它不是那样工作的。我也不能使用前向声明。有办法吗?

或者,是否有一种方法可以TB在该interface部分中声明但使其具有某种私有性?

回答

类型在声明之前不能使用(就行号而言)。特别是,这意味着您不能使用在implementation节中的interface节中声明的类型。

但是,请考虑以下示例:

unit VisibilityTest;

interface

type
  TFrog = class
  strict private type
    TFrogMetabolism = class
      procedure DoAnabolismStuff;
      procedure DoCatabolismStuff;
    end;
  strict private
    FMetabolism: TFrogMetabolism;
  public
    procedure Croak;
    procedure Walk;
    procedure Jump;
  end;

implementation

{ TFrog.TFrogMetabolism }

procedure TFrog.TFrogMetabolism.DoAnabolismStuff;
begin

end;

procedure TFrog.TFrogMetabolism.DoCatabolismStuff;
begin

end;

{ TFrog }

procedure TFrog.Jump;
begin

end;

procedure TFrog.Croak;
begin

end;

procedure TFrog.Walk;
begin

end;

end.

在这里,TFrog类是给其他单位,以及其明显的CroakWalkJump方法。

并且它确实有一个(strict private在这个例子中)类型的字段,由于前面的规范TFrogMetabolism,这个类型只能在内部使用TFrog——因此只能在这个单元内部使用strict private

这应该会给你一些想法。一些变体是可能的:

  • 如果strict从 中删除strict private type,则TFrogMetabolism该类可以在此特定单元内的任何地方使用,而不仅仅是在TFrog.

  • 如果替换privateprotected,则该类也可用于不是TFrog但派生自 的类中TFrog


回答

你可以做到,但要付出代价。在 TA 类中,引用 TB 的变量必须是 TObject 类型。让我们将该变量命名为 B。您可以将类 TB 的一个实例分配给该变量,例如从构造函数中。然后当 TA 中的代码需要使用变量 B 时,它必须强制转换为 TB(硬转换或使用“As”运算符)。

您还应该禁用该 TB 上的 RTTI,以便外部无法发现 TB 内部的内容。

这是代码:

unit Unit24;

interface

uses
    System.SysUtils;

type
    TA = class
        B : TObject;  // Will contain a TB instance
        constructor Create;
        destructor Destroy; override;
        procedure Demo;
    end;

implementation

type
    TB = class
        procedure SayHello;
    end;

{ TA }

constructor TA.Create;
begin
    inherited Create;
    B := TB.Create;
end;

procedure TA.Demo;
begin
    TB(B).SayHello;
end;

destructor TA.Destroy;
begin
    FreeAndNil(B);
    inherited Destroy;
end;

{ TB }

procedure TB.SayHello;
begin
    WriteLn('Hello!');
end;

end.

使用示例:

program Project24;

{$APPTYPE CONSOLE}

{$R *.res}

uses
  System.SysUtils,
  Unit24 in 'Unit24.pas';

var
  A : TA;
begin
  A := TA.Create;
  try
      A.Demo;
  finally
      A.Free;
  end;
end.


以上是是否可以使用在接口部分的实现部分中声明的类的全部内容。
THE END
分享
二维码
< <上一篇
下一篇>>