valores una tanteo resuelve realizar polinomios metodo iterativo iterar iteraciones ecuaciones ecuacion datos con como ciclo delphi list generics interface
http://www.bjmsoftware.com/delphistuff//interfacedlist.zip

delphi - tanteo - ¿Cómo hacer una iteración de soporte de interfaz correctamente?



resolver ecuaciones con solver excel (2)

¿Cómo puedo exponer este TList de una interfaz, como IEnumerator o IEnumerator<IFungibleTroll> ? Estoy usando Delphi XE.

Aquí está lo lejos que conseguí:

unit FungibleTrollUnit; interface uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Generics.Collections; type IFungibleTroll = interface [''{03536137-E3F7-4F9B-B1F5-2C8010A4D019}''] function GetTrollName:String; function GetTrollRetailPrice:Double; end; TFungibleTrolls = class (TInterfacedObject,IEnumerable<IFungibleTroll>) protected FTrolls:TList<IFungibleTroll>; public // IEnumerable function GetEnumerator:IEnumerator<IFungibleTroll>;// // function GetEnumerator:IEnumerator; overload; // find/search app feature requires searching. // this function FindSingleItemByName(aName:String;patternMatch:Boolean):IFungibleTroll; function FindMultipleItemsByName(aName:String;patternMatch:Boolean):IEnumerable<IFungibleTroll>; function FindSingleItemByIdentifier(anIdentifer:String):IFungibleTroll;// use internal non-visible identifier to find an app. constructor Create; property Trolls:TList<IFungibleTroll> read FTrolls; // implements IEnumerable<IFungibleTroll>;?? private end; implementation { TFungibleTrolls } constructor TFungibleTrolls.Create; begin FTrolls := TList<IFungibleTroll>.Create; end; function TFungibleTrolls.FindMultipleItemsByName(aName: String; patternMatch: Boolean): IEnumerable<IFungibleTroll>; begin end; function TFungibleTrolls.FindSingleItemByIdentifier( anIdentifer: String): IFungibleTroll; begin end; function TFungibleTrolls.FindSingleItemByName(aName: String; patternMatch: Boolean): IFungibleTroll; begin end; function TFungibleTrolls.GetEnumerator: IEnumerator<IFungibleTroll>; begin result := FTrolls.GetEnumerator; end; //function TFungibleTrolls.GetEnumerator: IEnumerator; //begin // result := FTrolls.GetEnumerator; // type IEnumerator<IFungibleTroll> or IEnumerator? //end; end.

Me quedo atascado en uno de los tres errores que no logro resolver:

[DCC Error] FungibleTrollUnit.pas(26): E2252 Method ''GetEnumerator'' with identical parameters already exists -o--

[DCC Error] FungibleTrollUnit.pas(19): E2291 Missing implementation of interface method IEnumerable.GetEnumerator -o-- [DCC Error] FungibleTrollUnit.pas(19): E2291 Missing implementation of interface method IEnumerable.GetEnumerator

Parece que debo declarar dos formas de GetEnumerator, si declaro TFungibleTrolls para implementar IEnumerable, pero parece que no puedo encontrar la manera de hacerlo, ya sea con sobrecargas, o sin sobrecargas, o usando una "cláusula de resolución de método", como esta:

function IEnumerable.GetEnumerator = GetPlainEnumerator; // method resolution clause needed? function GetEnumerator:IEnumerator<IFungibleTroll>; function GetPlainEnumerator:IEnumerator;

Esto probablemente parezca un uso bastante básico de IEnumerable, y hacer una iteración de soporte de la Interfaz, y sin embargo, estoy atascado.

Actualización: parece que cuando trato de hacer esto sin declarar primero una List<T> , estoy cayendo en una grieta causada por el hecho de que IEnumerable<T> hereda de IEnumerable , y aún así, en vez de un solo método get enumerator, mi la clase debe proporcionar varias y, como mi clase no es genérica, no puede "asignarse a sí misma" a los requisitos de IEnumerable directamente a menos que use una declaración genérica de la List<T> . El ejemplo de Marjan funciona cuando se compila en un proyecto (.dproj + .dpr) pero no cuando se integra en un paquete (.dproj + .dpk) y se compila en el IDE. Funciona bien desde la línea de comandos, en un paquete, pero no en el IDE, en un paquete.


No es una respuesta a su pregunta directamente (sigue trabajando en eso), pero esto es lo que hice para obtener un "enumerador interconectado", es decir, una clase interconectada que admite la iteración:

IList<T> = interface(IInterface) [...] function GetEnumerator: TList<T>.TEnumerator; function Add(const Value: T): Integer; end; type TBjmInterfacedList<T> = class(TBjmInterfacedObject, IList<T>) strict private FList: TList<T>; function GetEnumerator: TList<T>.TEnumerator; strict protected function Add(const Value: T): Integer; public constructor Create; override; destructor Destroy; override; end; implementation constructor TBjmInterfacedList<T>.Create; begin inherited; FList := TList<T>.Create; end; destructor TBjmInterfacedList<T>.Destroy; begin FreeAndNil(FList); inherited; end; function TBjmInterfacedList<T>.GetEnumerator: TList<T>.TEnumerator; begin Result := FList.GetEnumerator; end; function TBjmInterfacedList<T>.Add(const Value: T): Integer; begin Result := FList.Add(Value); end;

Y luego puedes hacer cosas como estas:

ISite = interface(IInterface) ... end; ISites = interface(IList<ISite>); ... end; var for Site in Sites do begin ... end;

con implementar clases como:

TSite = class(TBjmInterfacedObject, ISite) ... end; TSites = class(TBjmInterfacedList<ISite>, ISites) ... end;

Actualizar

Ejemplo de fuente del proyecto cargada en http://www.bjmsoftware.com/delphistuff//interfacedlist.zip


Si realmente desea crear una clase que implemente IEnumerable <T>, puede hacerlo así:

unit uGenericEnumerable; interface uses SysUtils, Classes, Generics.Collections; type TGenericEnumerator<T> = class(TInterfacedObject, IEnumerator, IEnumerator<T>) private FList: TList<T>; FIndex: Integer; protected function GenericGetCurrent: T; public constructor Create(AList: TList<T>); procedure Reset; function MoveNext: Boolean; function GetCurrent: TObject; function IEnumerator<T>.GetCurrent = GenericGetCurrent; property Current: T read GenericGetCurrent; end; type TNonGenericEnumerable = class(TInterfacedObject, IEnumerable) protected function GetNonGenericEnumerator: IEnumerator; virtual; abstract; public function IEnumerable.GetEnumerator = GetNonGenericEnumerator; end; type TGenericEnumerable<T> = class(TNonGenericEnumerable, IEnumerable<T>) private FList: TList<T>; public constructor Create; destructor Destroy; override; function GetNonGenericEnumerator: IEnumerator; override; function GetEnumerator: IEnumerator<T>; property List: TList<T> read FList; end; implementation { TGenericEnumerator<T> } constructor TGenericEnumerator<T>.Create(AList: TList<T>); begin inherited Create; FList := AList; FIndex := -1; end; procedure TGenericEnumerator<T>.Reset; begin FIndex := -1; end; function TGenericEnumerator<T>.MoveNext: Boolean; begin if FIndex < FList.Count then begin Inc(FIndex); Result := FIndex < FList.Count; end else begin Result := False; end; end; function TGenericEnumerator<T>.GenericGetCurrent: T; begin Result := FList[FIndex]; end; function TGenericEnumerator<T>.GetCurrent: TObject; begin // If T has not been constrained to being a class, raise an exception instead of trying to return an object. raise Exception.Create(''Cannot use this as a non-generic enumerator''); // If T has been constrained to being a class, return GenericGetCurrent. // Result := GenericGetCurrent; end; { TGenericEnumerable<T> } constructor TGenericEnumerable<T>.Create; begin inherited Create; FList := TList<T>.Create; end; destructor TGenericEnumerable<T>.Destroy; begin FList.Free; end; function TGenericEnumerable<T>.GetEnumerator: IEnumerator<T>; begin Result := TGenericEnumerator<T>.Create(FList); end; function TGenericEnumerable<T>.GetNonGenericEnumerator: IEnumerator; begin Result := GetEnumerator; end; end.

Ahora, tu FungibleTrollUnit tendrá un aspecto similar a este:

unit FungibleTrollUnit; interface uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Generics.Collections, uGenericEnumerable; type IFungibleTroll = interface [''{03536137-E3F7-4F9B-B1F5-2C8010A4D019}''] function GetTrollName:String; function GetTrollRetailPrice:Double; end; IFungibleTrolls = interface(IEnumerable<IFungibleTroll>) [''{090B45FB-2925-4BFC-AE97-5D3F54E1C575}''] function GetTrolls: TList<IFungibleTroll>; function FindSingleItemByName(aName:String):IFungibleTroll; function FindMultipleItemsByName(aName:String):IEnumerable<IFungibleTroll>; property Trolls:TList<IFungibleTroll> read GetTrolls; end; TFungibleTrolls = class (TGenericEnumerable<IFungibleTroll>, IFungibleTrolls, IEnumerable<IFungibleTroll>) public function GetTrolls: TList<IFungibleTroll>; function FindSingleItemByName(aName: String): IFungibleTroll; function FindMultipleItemsByName(aName: String): IEnumerable<IFungibleTroll>; property Trolls:TList<IFungibleTroll> read GetTrolls; private end; implementation uses StrUtils; { TFungibleTrolls } function TFungibleTrolls.GetTrolls: TList<IFungibleTroll>; begin Result := List; end; function TFungibleTrolls.FindMultipleItemsByName(aName: String): IEnumerable<IFungibleTroll>; var FilteredTrolls: TGenericEnumerable<IFungibleTroll>; var Troll: IFungibleTroll; begin FilteredTrolls := TGenericEnumerable<IFungibleTroll>.Create; for Troll in List do begin if Troll.GetTrollName = aName then FilteredTrolls.List.Add(Troll); end; Result := IEnumerable<IFungibleTroll>(FilteredTrolls); end; function TFungibleTrolls.FindSingleItemByName(aName: String): IFungibleTroll; var Troll: IFungibleTroll; begin Result := nil; for Troll in List do begin if Troll.GetTrollName = aName then Result := Troll; break; end; end; end.

Tenga en cuenta que la implementación de IEnumerable no funciona, pero IEnumerable <T> sí funciona.
Esto se debe a que, a menos que T esté restringido, no puede convertir una T en un TObject.
Si T es una cadena o un entero, por ejemplo, entonces IEnumerator no tiene un TObject para devolver.

Si T tiene restricciones para ser una clase, puede lograr que la implementación de IEnumerable funcione.
Si constriñes que T sea una interfaz intrasectorial, podría hacer que IEnumerable funcione (Delphi 2010 y después (convertir GenericGetCurrent en una interfaz secundaria, luego en un TObject), pero dudo que sea una ventaja.

Prefiero usarlo sin las restricciones, y lo hago sin poder iterar todo como TObjects.

TGenericEnumerable <T> .GetEnumerator no puede usar FList.GetEnumerator porque TList <T> .GetEnumerator no devuelve un IEnumerator <T>

Aunque puede implementar TGenericEnumerable <T> sin definir TNonGenericEnumerable, así:

type TGenericEnumerable<T> = class(TInterfacedObject, IEnumerable, IEnumerable<T>) private FList: TList<T>; protected function GenericGetEnumerator: IEnumerator<T>; public constructor Create; destructor Destroy; override; function GetEnumerator: IEnumerator; function IEnumerable<T>.GetEnumerator = GenericGetEnumerator; property List: TList<T> read FList; end;

la desventaja de hacer esto es que si intenta iterar utilizando el objeto TGenericEnumerable <T>, en lugar de la interfaz, GetEnumerator no será genérico y solo podrá iterar TObjects.

Advertencias habituales sobre la mezcla de referencias a una interfaz y su objeto subyacente. Si se refiere a un objeto como un tipo de objeto y como un IEnumerable <....>, cuando el recuento de referencia de la interfaz vuelve a cero, el objeto se liberará incluso si todavía tiene una referencia como objeto . (Es por eso que definí IFungibleTrolls, para poder referirme a la colección como una interfaz).

Puede realizar implementaciones alternativas de TGenericEnumerator <T>; por ejemplo, podría contener una referencia a una lista, un índice y un predicado de selección, que se suministran todos en el constructor.