我们有一个完美运行的软件项目(Delphi XE5)。它基本上显示了包含各种元素的图表。现在为了扩展它,我们必须重新实现绘图方法,这也很好。但是,然后我们遇到继承类中其他函数的不兼容类型问题。
描述图元素的单位:
unit Elements;
type
TElementA = class
procedure DrawSomething; virtual;
end;
TElementB = class
FElementA: TElementA;
procedure DrawSomething; virtual;
function ReturnSomething: TElementA;
end;
第二个单位使用第一个单位并基本上重新实现绘图程序:
unit ElementsDiff;
uses Elements;
type
TElementA = class(Elements.TElementA)
procedure DrawSomething; override;
end;
TElementB = class(Elements.TElementB)
procedure DrawSomething; override;
end;
使用这些类的过程如下所示:
unit Main;
uses
Elements,
ElementsDiff;
implementation
procedure MainProcedure;
var
FElementA: TElementA;
FElementB: TElementB;
begin
FElementA := TElementA.Create;
FElementB := TElementB.Create;
// do some stuff...
// ................
FElementA := FElementB.ReturnSomething;
end;
编译时,它当然没有编译最后一行的原因。我们得到一个很好的错误:
Incompatible types: 'ElementsDiff.TElementA' and 'Elements.TElementA'
含义:ReturnSomething返回类型' Elements.TElementA',但FElementA的类型为' ElementsDiff.TElementA'。 我理解问题的原因(这里已经多次回答了),最简单的解决办法就是做一个类型转换,即
FElementA := TElementA(FElementB.ReturnSomething);
但是因为它是一个相当大的软件项目,比上面的代码复杂得多,我想知道它是否真的是更好的解决方案,而不仅仅是类型转换每次使用该功能时。
非常感谢任何关于如何以一种很好的方式解决这个问题的想法。
答案 0 :(得分:1)
包含的最后一个单元'拥有'碰撞时的类型名称。由于这是包含子类的单元ElementsDiff
,因此主代码使用这些类。
问题是,ReturnSomething返回基类Elements.TElementA
的实例。
要解决这个问题,您可以(在其他方面)在Main中声明您的变量,如下所示:
var
FElementA: Elements.TElementA;
FElementB: Elements.TElementB;
这样,只要您不使用仅存在于后代中的任何方法或属性,变量就可以包含基类或后代类。
但也许最好给差异类别命名以避免混淆。这些类不必具有相同的名称。这也有效:
// In ElementDiff:
TElementBDiff = class(TElementB)
// In Main:
var
ElementB: TElementB;
begin
ElementB := TElementBDiff.Create;
答案 1 :(得分:0)
解决这些名称冲突的最简单方法是在Main。单元中提供一个本地别名:
type
TElementA = Elements.TElementA;
TElementB = Elements.TElementB;
这样,编译器就知道你要使用哪个TElementA。
答案 2 :(得分:0)
我认为你正在寻找这样的东西:
TElementB = class(Elements.TElementB)
procedure DrawSomething; override;
function ReturnSomething: tElementA; reintroduce;
end;
请注意,当您实现新的ReturnSomething时,您总是返回一个ElementsDiff.tElementA类型的对象。
我建议使用AS而不是显式的类型转换。
FElementA := FElementB.ReturnSomething as tElementA;
这将确保对象真正属于您期望的类型。