首页 > 解决方案 > 更改继承类中的类字段类型

问题描述

我正在使用最新的 Delphi 10.3.3

我有几个主类,它们是从同一个父类扩展而来的,还有一些,我们称之为反射类,它们也有相同的父类。我希望主类的实例能够链接到相应的反射实例,但我遇到了这个问题(我将其简化为这个例子):

主要课程:

TMainClass = class
  Link: TReflectionClass;
end;
TCarMainClass = class(TMainClass)
  Link: TCarReflectionClass;
end;

反射类:

TReflectionClass = class;
TCarReflectionClass = class(TReflectionClass);

问题在于链接字段。我希望将 TCarMainClass 中的 Link 字段直接定义为 TCarReflectionClass 以避免对大量代码进行类型转换(并且还会冒一些错误的风险),但是如果我这样定义类, TCarMainClass.Link 只是隐藏 TMainClass.Link - 它是定义为具有相同名称的不同字段。这不好,因为它消耗额外的内存,主要是我无法从我想要的父类访问该字段(作为指向通用实例的指针)。

当然,我可以通过将字段设为公共类型私有并定义处理每个类中重新键入的属性设置器/获取器来解决这个问题。但这对于这些类来说是很多额外的代码,而且由于调用 getter/setter 方法,每个 get/set 也会产生开销。

我的问题是 - 我是否错过了一些简单的技巧,告诉编译器我希望子类中的字段与父类中的某些字段占用相同的内存位置?

谢谢

标签: oopdelphipascal

解决方案


主要是我无法从父类访问该字段

虽然父类确实无法访问后代的字段,但没有什么可以阻止您同步 2.

procedure TCarMainClass.SetLink(const Value : TCarReflectionClass);
begin
  FLink := Value;
  TMainClass(Self).FLink := Value;
end;

现在,如果您绝对不需要额外的内存使用和设置器,那么唯一剩下的选项(我此时能想到的)就是 GolezTrol 建议的泛型。

TMainClass<T : TReflectionClass> = class
  Link: T;
end;

TCarMainClass = class(TMainClass<TCarReflectionClass>)
end;

但这可能会破坏您的设计,因为 TCarMainClass 将与TMainClass<TReflectionClass>. (如果您想了解原因,请搜索术语协变/逆变)。


推荐阅读