是否可以使用在接口部分的实现部分中声明的 class
Is it possible to use a class declared in Implementation section from Interface section
如果我没理解错,interface
段对其他单位可见,implementation
段只在当前.pas
文件可见
我有两个class,classTA
应该是外面可见的,其他的classTB
不应该,但是我需要一个TA
.
中 TB
类型的字段
interface
type
TA = class
//something
B : TB;
end;
//something
implementation
type
TB = class
//something
end;
不是这样的。我也不能使用前向声明。有办法吗?
或者,有没有办法在 interface
部分中声明 TB
但使其有点私有?
Is it possible to use a class declared in Implementation section from Interface section?
没有
Or is there a way to declare TB in the Interface section but make it kinda private?
是的,如果您将其设为嵌套 class,请在包含类型的私有部分中声明。
类型在声明之前不能使用(根据行号)。特别是,这意味着您不能在 interface
部分中使用在 implementation
部分中声明的类型。
但是,请考虑以下示例:
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
class 对其他单位可见,以及它的 Croak
、Walk
和 Jump
方法。
它确实有一个(strict private
在本例中)类型为 TFrogMetabolism
的字段,该类型只能在 TFrog
内部使用——因此只能在该单元内部使用-- 由于前面的 strict private
规范。
这应该会给您一些想法。可能有几种变体:
如果从 strict private type
中删除 strict
,则 TFrogMetabolism
class 可以在这个特定单元内的任何地方使用,而不仅仅是 TFrog
.
如果您将 private
替换为 protected
,则 class 也可以用于 class 而非 TFrog
] 但派生自 TFrog
.
一个选项可能是声明 TB
实现的 public interface
,然后 TA
可以拥有该接口类型的字段。
interface
type
IB = interface
//something
end;
TA = class
public
B : IB;
constructor Create;
end;
//something
implementation
type
TB = class(TInterfacedObject, IB)
//something
end;
constructor TA.Create;
begin
B := TB.Create;
end;
你可以做到,但要付出代价。在classTA中,引用TB的变量必须是TObject类型。让我们将该变量命名为 B。您可以将 class 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.
指针和class可以向前声明,但必须在同一类型块中声明。这样做的原因是因为它们是引用类型,甚至只是前向声明就固定了它们之后字段的偏移量。类型块位主要是为了方便编译器编写者(但通常也会 easier/better 生成错误消息)
Pascal 后续 Modula2 允许在实现中更严格地定义指针,例如指向某个记录的指针(所谓的不透明类型)。其他单元只能将它用作句柄类型(传递它等),并且实现可以在没有类型转换的情况下访问细节。通过这种方式,它是一种语言辅助方式来执行 Fpiette 建议的操作,对象是 class.
的最基本子集
另一种解决方案是使其成为通用的,并专门用于通用 TB 类型的实现。
如果我没理解错,interface
段对其他单位可见,implementation
段只在当前.pas
文件可见
我有两个class,classTA
应该是外面可见的,其他的classTB
不应该,但是我需要一个TA
.
TB
类型的字段
interface
type
TA = class
//something
B : TB;
end;
//something
implementation
type
TB = class
//something
end;
不是这样的。我也不能使用前向声明。有办法吗?
或者,有没有办法在 interface
部分中声明 TB
但使其有点私有?
Is it possible to use a class declared in Implementation section from Interface section?
没有
Or is there a way to declare TB in the Interface section but make it kinda private?
是的,如果您将其设为嵌套 class,请在包含类型的私有部分中声明。
类型在声明之前不能使用(根据行号)。特别是,这意味着您不能在 interface
部分中使用在 implementation
部分中声明的类型。
但是,请考虑以下示例:
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
class 对其他单位可见,以及它的 Croak
、Walk
和 Jump
方法。
它确实有一个(strict private
在本例中)类型为 TFrogMetabolism
的字段,该类型只能在 TFrog
内部使用——因此只能在该单元内部使用-- 由于前面的 strict private
规范。
这应该会给您一些想法。可能有几种变体:
如果从
strict private type
中删除strict
,则TFrogMetabolism
class 可以在这个特定单元内的任何地方使用,而不仅仅是TFrog
.如果您将
private
替换为protected
,则 class 也可以用于 class 而非TFrog
] 但派生自TFrog
.
一个选项可能是声明 TB
实现的 public interface
,然后 TA
可以拥有该接口类型的字段。
interface
type
IB = interface
//something
end;
TA = class
public
B : IB;
constructor Create;
end;
//something
implementation
type
TB = class(TInterfacedObject, IB)
//something
end;
constructor TA.Create;
begin
B := TB.Create;
end;
你可以做到,但要付出代价。在classTA中,引用TB的变量必须是TObject类型。让我们将该变量命名为 B。您可以将 class 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.
指针和class可以向前声明,但必须在同一类型块中声明。这样做的原因是因为它们是引用类型,甚至只是前向声明就固定了它们之后字段的偏移量。类型块位主要是为了方便编译器编写者(但通常也会 easier/better 生成错误消息)
Pascal 后续 Modula2 允许在实现中更严格地定义指针,例如指向某个记录的指针(所谓的不透明类型)。其他单元只能将它用作句柄类型(传递它等),并且实现可以在没有类型转换的情况下访问细节。通过这种方式,它是一种语言辅助方式来执行 Fpiette 建议的操作,对象是 class.
的最基本子集另一种解决方案是使其成为通用的,并专门用于通用 TB 类型的实现。