delphi – 为接口变量或参数分配一个匿名方法?

前端之家收集整理的这篇文章主要介绍了delphi – 为接口变量或参数分配一个匿名方法?前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
匿名方法本质上是与Invoke方法的接口:
  1. type
  2. TProc = reference to procedure;
  3.  
  4. IProc = interface
  5. procedure Invoke;
  6. end;

现在,是否有可能将它们分配给实际的接口变量或将其作为接口参数传递?

  1. procedure TakeInterface(const Value: IInterface);
  2. begin
  3. end;
  4.  
  5. var
  6. P: TProc;
  7. I: IInterface;
  8. begin
  9. I := P; // E2010
  10. TakeInterface(P); // E2010
  11. end;

[DCC32错误] E2010不兼容的类型:’IInterface’和’过程,无类型的指针或无类型参数’

问题:这是什么用例?

有很多对象在那里,不能简单地保持活着与接口参考.因此,他们被包裹在一个关闭并被毁坏与“Smart Pointers”

  1. type
  2. I<T> = reference to function : T;
  3.  
  4. TInterfaced<T: class> = class (TInterfacedObject,I<T>)
  5. strict private
  6. FValue: T;
  7. function Invoke: T; // Result := FValue;
  8. public
  9. constructor Create(const Value: T); // FValue := Value;
  10. destructor Destroy; override; // FValue.Free;
  11. end;
  12.  
  13. IInterfacedDictionary<TKey,TValue> = interface (I<TDictionary<TKey,TValue>>) end;
  14.  
  15. TKey = String;
  16. TValue = String;
  17.  
  18. var
  19. Dictionary: IInterfacedDictionary<TKey,TValue>;
  20. begin
  21. Dictionary := TInterfaced<TDictionary<TKey,TValue>>
  22. .Create(TDictionary<TKey,TValue>.Create);
  23. Dictionary.Add('Monday','Montag');
  24. end; // FRefCount = 0,closure with object is destroyed

现在,有时不仅要保持一个单一的对象活着,还需要一个上下文.想像你有一个TDictionary< TKey,TValue>并从中抽出一个计数器:TEnumerator&TK; TEnumerator< TValue>或TEnumerator< TPair< TKey,TValue>>.或者字典包含和拥有TObjects.然后两者,新对象和字典的关闭将进入一个新的关闭,以便创建一个单独的独立引用:

  1. type
  2. TInterfaced<IContext: IInterface; T: class> = class (TInterfacedObject,I<T>)
  3. strict private
  4. FContext: IContext;
  5. FValue: T;
  6. FFreeObject: Boolean;
  7. function Invoke: T; // Result := FValue;
  8. public
  9. constructor Create(const Context: IContext; const Value: T; const FreeObject: Boolean = True); // FValue = Value; FFreeObject := FreeObject;
  10. destructor Destroy; override; // if FFreeObject then FValue.Free;
  11. end;
  12.  
  13. IInterfacedEnumerator<T> = interface (I<TEnumrator<T>>) end;
  14.  
  15. TValue = TObject; //
  16.  
  17. var
  18. Dictionary: IInterfacedDictionary<TKey,TValue>;
  19. Enumerator: IInterfacedEnumerator<TKey>;
  20. Obj: I<TObject>;
  21. begin
  22. Dictionary := TInterfaced<TDictionary<TKey,TValue>>
  23. .Create(TObjectDictionary<TKey,TValue>.Create([doOwnsValues]));
  24. Dictionary.Add('Monday',TObject.Create);
  25.  
  26. Enumerator := TInterfaced<
  27. IInterfacedDictionary<TKey,TValue>,TEnumerator<TKey>
  28. >.Create(Dictionary,Dictionary.Keys.GetEnumerator);
  29.  
  30. Obj := TInterfaced<
  31. IInterfacedDictionary<TKey,TObject
  32. >.Create(Dictionary,Dictionary['Monday'],False);
  33.  
  34. Dictionary := nil; // closure with object still held alive by Enumerator and Obj.
  35. end;

现在的想法是融化TInterfaced< T>和TInterfaced< IContext,T>,这将使上下文的类型参数过时(一个界面就足够了),并导致这些主持人:

  1. constructor TInterfaced<T: class>.Create(const Value: T; const FreeObject: Boolean = True); overload;
  2. constructor TInterfaced<T: class>.Create(const Context: IInterface; const Value: T; const FreeObject: Boolean = True); overload;

作为(纯)关闭可能不是使用匿名方法时会想到的主要用途.然而,它们的类型可以被给出为类的接口,其对象可以在关闭的破坏时进行清理,并且TFunc< T>使其流畅地访问其内容.虽然它们不共享共同的祖先,但似乎对类型的引用的值不能分配给接口类型,这意味着没有统一,安全和未来的方式来引用所有类型的闭包来保持它们的存活.

解决方法

这是超级容易.我会给你两个方法.
  1. var
  2. P: TProc;
  3. I: IInterface;
  4. begin
  5. I := IInterface(Pointer(@P)^);
  6. TakeInterface(I);
  7. end;

另一种方法是声明PInterface

  1. type
  2. PInterface = ^IInterface;
  3. var
  4. P: TProc;
  5. I: IInterface;
  6. begin
  7. I := PInterface(@P)^;
  8. TakeInterface(I);
  9. end;

猜你在找的Delphi相关文章