Interface und Generics

Für Fragen zur Programmiersprache auf welcher Lazarus aufbaut
Antworten
soerensen3
Beiträge: 104
Registriert: Fr 22. Jun 2012, 01:51
OS, Lazarus, FPC: Fedora-Linux 23 (Korora) Lazarus 1.6 FPC 3.0
CPU-Target: 64Bit
Wohnort: Bonn

Interface und Generics

Beitrag von soerensen3 »

Was stimmt nicht mit folgender Interacedeklaration?

Code: Alles auswählen

 
interface
  uses
    Classes, sysutils;
 
  type
     { gP3DCustomListEnumerator }
     generic gP3DCustomListEnumerator < TCustomItem: TObject > = class ( TInterfacedPersistent, IEnumerator )
       private type
         TMoveNext = function ( var Index: Integer ): TCustomItem of object;
 
       private
         FCurrent: TCustomItem;
         FCurrentIdx: Integer;
         FMoveNext: TMoveNext;
         function GetCurrent(): TCustomItem;
         procedure Reset();
 
       public
         constructor Create( AMoveNext: TMoveNext );
         function MoveNext: Boolean;
         property Current: TCustomItem read GetCurrent;
         property CurrentIdx: Integer read FCurrentIdx;
     end;
 
    { gP3DCustomObjectList }
 
    generic gP3DCustomObjectList <TCustomItem: TObject> = class ( TInterfacedPersistent, IEnumerable ) //Hier kommt die Fehlermeldung
      type
        TP3DCustomObjectListEnumerator = specialize gP3DCustomListEnumerator < TCustomItem >;
 
      private
        FItems: TList;
        FOnChange: TNotifyEvent;
        function GetCount: Integer;
        procedure SetCount( AValue: Integer );
        function GetItems( Index: Integer ): TCustomItem;
        function MoveNext( var Index: Integer ): TCustomItem;
 
      public
        constructor Create;
        destructor Destroy; override;
 
        function Add( Item: TCustomItem ): Integer; virtual;
        procedure Delete( Index: Integer ); virtual;
        function IndexOf( Item: TCustomItem ): Integer; virtual;
        procedure Clear( const FreeObjects: Boolean = False ); virtual;
        function GetEnumerator(): TP3DCustomObjectListEnumerator;
        procedure Insert( Index: Integer; Item: TCustomItem );
 
        property Items[ Index: Integer ]: TCustomItem read GetItems; default;
        property OnChange: TNotifyEvent read FOnChange write FOnChange;
 
      published
        property Count: Integer read GetCount write SetCount;
    end;   
 


Fehler: p3dgenerics.pas(31,59) Error: No matching implementation for interface method "GetEnumerator:IEnumerator;" found

Meiner Meinung nach habe ich das doch implementiert (Die abgeleitete Klasse gP3DCustomListEnumerator implementiert IEnumerator), aber ich kenne mich noch nicht so gut mit Interfaces aus.

Gruß Johannes

marcov
Beiträge: 1100
Registriert: Di 5. Aug 2008, 09:37
OS, Lazarus, FPC: Windows ,Linux,FreeBSD,Dos (L trunk FPC trunk)
CPU-Target: 32/64,PPC(+64), ARM
Wohnort: Eindhoven (Niederlande)

Re: Interface und Generics

Beitrag von marcov »

gP3DCustomObjectList und TP3DCustomObjectListEnumerator sind Klasse (die Interfaces implementieren, aber immerhin Klassen).

IEnumerable.GetEnumerator muss aber ein (bestimmtes) Interface zurückgeben.

soerensen3
Beiträge: 104
Registriert: Fr 22. Jun 2012, 01:51
OS, Lazarus, FPC: Fedora-Linux 23 (Korora) Lazarus 1.6 FPC 3.0
CPU-Target: 64Bit
Wohnort: Bonn

Re: Interface und Generics

Beitrag von soerensen3 »

Das stimmt! So klappt es.

Falls es jemanden interessiert, der header sieht jetzt so aus:

Code: Alles auswählen

 
    generic IP3DEnumerator < TCustomItem: TObject >  = interface
      ['{B873CDC1-491F-4F62-A1F8-CED1C13426C4}']
      function GetCurrent: TCustomItem;
      function MoveNext: Boolean;
      procedure Reset;
      property Current: TCustomItem read GetCurrent;
    end;
    generic IP3DEnumerable < TCustomItem: TObject >  = interface
      ['{A8D955A0-E3A9-4BF5-8CDF-8A21AB3E2A06}']
      function GetEnumerator: specialize IP3DEnumerator < TCustomItem >;
    end;
 
     { gP3DCustomListEnumerator }
     generic gP3DCustomListEnumerator < TCustomItem: TObject > = class ( TInterfacedPersistent, specialize IP3DEnumerator < TCustomItem >)
       private type
         TMoveNext = function ( var Index: Integer ): TCustomItem of object;
 
       private
         FCurrent: TCustomItem;
         FCurrentIdx: Integer;
         FMoveNext: TMoveNext;
         function GetCurrent(): TCustomItem;
         procedure Reset();
 
       public
         constructor Create( AMoveNext: TMoveNext );
         function MoveNext: Boolean;
         property Current: TCustomItem read GetCurrent;
         property CurrentIdx: Integer read FCurrentIdx;
     end;
 
    { gP3DCustomObjectList }
 
    generic gP3DCustomObjectList <TCustomItem: TObject> = class ( TInterfacedPersistent, specialize IP3DEnumerable < TCustomItem > )
      type
        TP3DCustomObjectListEnumerator = specialize gP3DCustomListEnumerator < TCustomItem >;
 
      private
        FItems: TList;
        FOnChange: TNotifyEvent;
        function GetCount: Integer;
        procedure SetCount( AValue: Integer );
        function GetItems( Index: Integer ): TCustomItem;
        function MoveNext( var Index: Integer ): TCustomItem;
 
      public
        constructor Create;
        destructor Destroy; override;
 
        function Add( Item: TCustomItem ): Integer; virtual;
        procedure Delete( Index: Integer ); virtual;
        function IndexOf( Item: TCustomItem ): Integer; virtual;
        procedure Clear( const FreeObjects: Boolean = False ); virtual;
        function GetEnumerator: specialize IP3DEnumerator < TCustomItem >;
        //IP3DEnumerator.GetEnumerator = GetEnumerator;
        procedure Insert( Index: Integer; Item: TCustomItem );
 
        property Items[ Index: Integer ]: TCustomItem read GetItems; default;
        property OnChange: TNotifyEvent read FOnChange write FOnChange;
 
      published
        property Count: Integer read GetCount write SetCount;
    end
 


Weiß nicht ob das vom Compiler her so gedacht ist mehrer Interfaces (Es ist ja ein Generic) mit der gleichen GUID zu verwenden aber es funktioniert und wenn man die Supports Funktion benutzen will brauch man das ja anscheinend.

Danke!

Antworten