【问题标题】:Why does the compiler say the implementation "differs from the previous declaration" when they look identical?当它们看起来相同时,为什么编译器会说实现“与先前的声明不同”?
【发布时间】:2011-05-24 20:58:47
【问题描述】:

我有两个单位, 第一个,我的界面:

use personas

interface

type
  Tllave = array[0..31] of byte;
  Tdatos = array of byte;

  ImyInterface = interface(IInterface)

    function nombre : string;
    function edad : integer;
    procedure resetear;
    function Proceso(datos : tdatos; cantidad : integer) : integer ;    
    procedure Iniciar(llave : Tllave);
  end;

第二个单元,我的对象声明:

use militares

interface

uses personas;

type

  Tmilitares = Class(TInterfacedObject, ImyInterface )
    public
      function nombre : string;
      function edad : integer;
      procedure resetear;
      function Proceso(datos : Tdatos; cantidad : integer) : integer ;    
      procedure Iniciar(llave : Tllave);
    published
      constructor create;
  end;

implementation

function tmilitares.Proceso(datos : tdatos; cantidad : integer) : integer ; // getting error !!
begin
  // ....
end;


procedure tmilitares.Iniciar(llave : Tllave); // getting error!!
begin
  // ....
end;

我只在“proceso”函数和“iniciar”程序中收到错误消息:

“Iniciar”声明与之前的声明不同
'Proceso' 的声明与之前的声明不同。

我注意到他们有数组参数。参数的类型在第一个单元中定义,如果我在第二个单元中定义这些类型,我会得到相同的错误,但它显示在对象的声明中。怎么编译?

【问题讨论】:

  • 您没有向我们展示足够的细节。还有其他原因导致这些错误。
  • 在第 1 行的两个 sn-ps 中必须有 uses,而不是 use
  • 没有那些行应该说unit

标签: arrays delphi interface parameters tinterfacedobject


【解决方案1】:

您没有显示足够的代码,但很明显,您正在重新定义接口部分中 Tmilitares 的声明和方法的实现之间的违规类型(TdatosTllave)。这种重新声明要么是您use 的另一个单元的形式,要么是militares 单元的实现部分。

找到那些其他的声明,你就能解决你的问题。


您在问题末尾的评论说明了:

如果我在第二个单元中定义这些类型,我会得到相同的错误,但它会显示在类的声明中。

您尝试重新定义类型的事实表明存在理解问题。类型只需要声明一次。一旦你定义了它们两次,你现在就有了两种截然不同的不兼容类型。更糟糕的是,他们的名字是一样的!定义一次类型,然后通过uses 语句将其导入其他单元。

【讨论】:

  • 这里的关键是,如果你在两个地方定义它,你最终会得到两种不同的类型:unit1.Tdatos 和 unit2.Tdatos。您也可以指定单位以使其工作,但最好只定义一次。
【解决方案2】:

以下作品。没有不匹配的先前声明。我怀疑您正在声明 iMyInterface.SomeProcedure(在我的示例中为 unit1),其参数与您在实现接口的类(在我的示例中为 unit2)部分中显示的参数略有不同。请注意,任何实现 ImyInterface 的东西都必须实现它的ALL

单元1:

unit Unit1;


interface

type   
  Tllave = array[0..31] of byte;  

  Tdatos = array of byte;

  ImyInterface = interface(IInterface)

    function nombre : string;
    function edad : integer;
    procedure resetear;
    function Proceso(datos : tdatos; cantidad : integer) : integer ;
    procedure Iniciar(llave : Tllave);   end;

implementation


  //stuff.

end.

单元2:

unit Unit2;

interface

{$M+}

uses Unit1;

type

  Tmilitares = Class(TInterfacedObject, ImyInterface )
    public
      function nombre : string;
      function edad : integer;
      procedure resetear;
      function Proceso(datos : Tdatos; cantidad : integer) : integer ;    
      procedure Iniciar(llave : Tllave);
    published
      constructor create;
  end;

implementation


function Tmilitares.nombre: string;
begin

end;

function tmilitares.Proceso(datos : tdatos; cantidad : integer) : integer ; // no more error 
begin
  // ....
end;


constructor Tmilitares.create;
begin

end;

function Tmilitares.edad: integer;
begin

end;

procedure Tmilitares.resetear;
begin

end;

procedure tmilitares.Iniciar(llave : Tllave); // no more error.
begin
  // ....
end;

end.

【讨论】:

    【解决方案3】:

    我在这里添加这个作为答案,因为这是一个非常相似的问题,但我只是在一个看起来像这样的单元中遇到了这个:

    unit Unit1;
    
    interface
      uses Generics.Collections;
    
    type
      TFoo = class
      end;
    
      TFooList = class(TObjectList<TFoo>)
        protected
          procedure Notify(const Item: TFoo; Action: TCollectionNotification); override;
      end;
    
    implementation
    
    uses Classes;
    
    procedure TFooList.Notify(const Item: TFoo; Action: TCollectionNotification);
    var
     sl : TStringList;
    begin
      //
    end;
    
    end.
    

    [dcc32 错误] Unit1.pas(20):“通知”的 E2037 声明与之前的声明不同
    [dcc32 错误] Unit1.pas(12): E2065 Unsatisfied forward or external declaration: 'TFooList.Notify' [dcc32 致命错误] Project1.dpr(6): F2063 无法编译使用的单元'Unit1.pas'

    我花了比我想承认的时间更长的时间来弄清楚有一个

    System.Classes :: TCollectionNotification = (cnAdded, cnExtracting, cnDeleting);
    

    还有一个:

    System.Generics.Collections :: TCollectionNotification = (cnAdded, cnRemoved, cnExtracted);
    

    课程是有条不紊地检查你的类型。类型标识符上的 Ctrl+CLICK 将带您进入编译器正在使用的类型的定义。要修复它,请重新组织您的 uses 子句或使用完全限定的类型名称。

    在我们自己的代码中重复类型名称的新手错误已经够糟糕了,当 Emba 在他们自己的 RTL 中这样做时更糟糕。

    【讨论】:

      猜你喜欢
      • 2010-12-08
      • 1970-01-01
      • 2012-03-24
      • 1970-01-01
      • 1970-01-01
      • 2010-12-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多