DXE7: "type A = type B" and var x (of type A):= A.create 导致 E2010 不兼容类型编译错误。为什么?

DXE7: "type A = type B" and var x (of type A):= A.create leads to E2010 incompatible type compile error. Why?

一个。问题的简短摘要:

type
  A = class(TObject)
  end;

  B = type A;

编译器错误E2010 incompatible types: 'B' and 'A',当你实例化class B 的一个变量时,如下样式:

var
  TheB: B;
begin
     TheB:= B.Create;
     ..

我可以通过删除第二个 "type" 来避免这个问题,所以声明是标准的:

type
  A = class(TObject)
  end;

  B = A;

但在我看来,错误不应该出现,即使是第二个 "type",因为 A 没有被直接使用(第二个 "type" 告诉编译器看到两个 class 作为个人,请参阅 http://docwiki.embarcadero.com/RADStudio/Seattle/en/Declaring_Types 了解详细信息)。有人可以解释一下,由于什么原因错误忽略了我的意见? (o;

乙。完整的历史和更复杂的细节:

首先:错误:

[dcc32 Fehler] gboDHL.pas(165): E2010 Inkompatible Typen: 'Origin' und 'CountryType' (英文意思是"incompatible types"),

出现在以下代码行中:

AShipmentOrder.Shipment.Shipper.Address.Origin:= DHL_geschaeftskundenversand_api_2.Origin.Create;

背景介绍:

我尝试与 "new" DHL Geschäftskundenversand API v2.2 沟通,它仍然使用 SOAP 创建装运订单。 DHL_geschaeftskundenversand_api_2 是从该服务的集成 delphi xe7 WSDL 生成器中完全生成的单元。 AShipmentOrder 是表示请求的顶级 xml 节点的实例。

class"Origin"是implemented/generated这样:

type    
  CountryType = class(TRemotable)
  private
    Fcountry: country2;
    Fcountry_Specified: boolean;
    FcountryISOCode: countryISOType;
    Fstate: state;
    Fstate_Specified: boolean;
    Fcountry_: country;
    Fcountry__Specified: boolean;
    FcountryISOCode_: countryISOType;
    Fstate_: state2;
    Fstate__Specified: boolean;
    procedure Setcountry(Index: Integer; const Acountry2: country2);
    function  country_Specified(Index: Integer): boolean;
    procedure Setstate(Index: Integer; const Astate: state);
    function  state_Specified(Index: Integer): boolean;
    procedure Setcountry_(Index: Integer; const Acountry: country);
    function  country__Specified(Index: Integer): boolean;
    procedure Setstate_(Index: Integer; const Astate2: state2);
    function  state__Specified(Index: Integer): boolean;
  published
    property country:         country2        Index (IS_OPTN) read Fcountry write Setcountry stored country_Specified;
    property countryISOCode:  countryISOType  read FcountryISOCode write FcountryISOCode;
    property state:           state           Index (IS_OPTN) read Fstate write Setstate stored state_Specified;
    property country_:        country         Index (IS_OPTN) read Fcountry_ write Setcountry_ stored country__Specified;
    property countryISOCode_: countryISOType  read FcountryISOCode_ write FcountryISOCode_;
    property state_:          state2          Index (IS_OPTN) read Fstate_ write Setstate_ stored state__Specified;
  end;

  Origin          =  type CountryType;      { "http://dhl.de/webservice/cisbase"[GblElm] }

AShipmentOrder.Shipment.Shipper.Address的"property"来源是implemented/generated这样:

type
 NativeAddressType = class(TRemotable)
 ...
 published
 ...
   property Origin: Origin  Index (IS_OPTN or IS_REF) read FOrigin write SetOrigin stored Origin_Specified;
 ...
 end;

如果不清楚,让我说,'AShipmentOrder.Shipment.Shipper.Address'是class NativeAddressType

我在 Windows 10、64 位上使用 Delphi XE7,正在编译为 32 位。

delphi WSDL 生成器有不同的问题,我之前必须解决这些问题,而且输出中的 属性 名称与 class 名字,但似乎是不可改变的。 class "Origin" 不是那个生成的单元中唯一的 class ,它被命名为它所属的 属性 ,但只有当这样的 class 实现为

type
 A = type B

我试图找到那个特殊声明变体的描述,但这很难,因为关键字太常用了。

http://www.delphibasics.co.uk/RTL.asp?Name=Type上找到了如下解释:

1.type Name = Existing type   Refers to an existing type, such as string by a new Name.   2.type Name = type Existing type   This has the same effect as above, but ensures that at run time, variables of this type are identified by their new type name, rather than the existing type name.

如果我理解正确,那意味着在我的示例中 class Origin 不再被识别为 CountryType,而是 Origin。那应该没问题,因为 属性 Origin 被声明为 class Origin

在继续尝试理解该问题时,我手动将生成的单元中的 class "Origin" 重命名为 OriginType(delphi 使用该后缀 "Type"该单元中的其他几个 classes,不清楚,为什么它没有将它与 Origin-Type 一起使用)。之后,我可以排除名称冲突,因为现在错误是

[dcc32 Fehler] gboDHL.pas(165): E2010 Inkompatible Typen: 'OriginType' und 'CountryType'

似乎没有原因,因为发生该错误。

经过几个小时的思考后,我发现了这个 Embarcadero WIKI 条目:http://docwiki.embarcadero.com/RADStudio/Seattle/en/Declaring_Types

看完想了想,我明白了,A = type B中的"type"在那种情况下是没有必要的,因为没有必要在另一个中处理classA方式比 class B,所以我在生成的单元中手动删除了它,现在它工作正常。

我也明白了,检查了生成器中的一个特殊选项以防止"name conflicts"。如果不勾选这个选项,这个问题也应该可以解决(但也许其他人会过来(o;))。

也许这可以帮助某人花更多的时间在户外而不是解决这样的问题 (o;

但最后,我不明白这里的问题是什么,因为所有属性都是"Origin"类型,后来是"OriginType",而且这个类型是用[=33=创建的] 之后 OriginType.Create。所以 "CountryType" 从未被使用过,除了 "Origin" / "OriginType" 的 class 声明。在我看来,这不应该导致那个问题,但确实如此。

有人可以解释一下吗?

提前致谢

您得到:E2010 Incompatible types: 'Tb' and 'Ta',这可能看起来很奇怪:

type
  Ta = class
  end;
  Tb = type Ta;
var
  b: Tb;
begin
  b := Tb.Create;  // E2010 Incompatible types: 'Tb' and 'Ta' 
end.

TaTb 是两种截然不同的类型。

Type Compatibility 可以看出,none 列出的条件表明两种不同的类型是兼容的。

Type Compatibility

Every type is compatible with itself. Two distinct types are compatible if they satisfy at least one of the following conditions.

  • They are both real types.
  • They are both integer types.
  • One type is a subrange of the other.
  • Both types are subranges of the same type.
  • Both are set types with compatible base types.
  • Both are packed-string types with the same number of characters.
  • One is a string type and the other is a string, packed-string, or Char type.
  • One type is Variant and the other is an integer, real, string, character, or Boolean type.
  • Both are class, class-reference, or interface types, and one type is derived from the other.
  • One type is PAnsiChar or PWideChar and the other is a zero-based character array of the form array[0..n] of PAnsiChar or PWideChar.
  • One type is Pointer (an untyped pointer) and the other is any pointer type.
  • Both types are (typed) pointers to the same type and the {$T+} compiler directive is in effect.
  • Both are procedural types with the same result type, the same number of parameters, and type-identity between parameters in corresponding positions.

编译器错误的原因是:当您调用 Tb.Create 时,编译器将其识别为 Ta.Create,因为 b 是不同的 non-compatible 类型, 不被接受。

您可以称其为缺陷,但它遵循严格的类型规则,并且可以很容易地进行更正,如下所示。


声明 Tb = class(Ta) 将解决编译器错误,因为 Tb 派生自 Ta


同时声明 Tb = Ta 将解决编译器错误,因为它们表示相同的类型(不是两种不同的类型),因此赋值兼容。