[英]How to use a helper generic of type class of type
I am trying to figure out how to genericize this helper method; 我试图弄清楚如何对这个辅助方法进行泛化 ; so that it returns the same type that was asked for:
以便它返回与要求相同的类型:
type
TScreenHelper = class helper for TScreen
public
function FindForm(DesiredFormClass: TFormClass): TForm;
end;
Right now the caller has to cast the return value to type they already want: 现在,调用者必须将返回值强制转换为他们已经想要的类型:
var
frmReportReminderSetup: TfrmReportReminderSetup;
begin
//frmReportReminderSetup := Screen.FindForm(TfrmReportReminderSetup); Doesn't compile
frmReportReminderSetup := TfrmReportReminderSetup(Screen.FindForm(TfrmReportReminderSetup));
The non-generic implementation is: 非通用实现是:
function TScreenHelper.FindForm(DesiredFormClass: TFormClass): TForm;
var
f: TForm;
i: Integer;
begin
Result := nil;
for i := 0 to Screen.FormCount-1 do //Screen.Forms does not support enumeration
begin
f := Screen.Forms[i];
if (f is DesiredFormClass) then
begin
Result := f;
Exit;
end;
end;
end;
What i want is some way to use generics so that the function returns the type it was asked for. 我想要的是一些使用泛型的方法,以便函数返回它所要求的类型。
frmContoso := Screen.FindForm(TfrmContoso);
In pseudo-code, the signature that i want would be something like: 在伪代码中,我想要的签名是这样的:
function FindForm(T: TFormClass): T;
When it comes time to turn this into actual Delphi syntax, i think you must specify one of the T references in angle brackets: 当需要将其转换为实际的Delphi语法时,我认为你必须在尖括号中指定一个T引用:
function FindForm(<T>): T;
But i don't think the 但我不认为 is allowed there;
允许在那里; i think it has to be before the opening parenthesis:
我认为它必须在前括号之前:
function FindForm<T>: T;
TScreenHelper = class helper for TScreen
public
function FindFormOld(DesiredFormClass: TFormClass): TForm;
function FindForm<T>: T;
end;
function TScreenHelper.FindForm<T>: T;
var
f: TForm;
i: Integer;
begin
Result := nil;
for i := 0 to Screen.FormCount-1 do //Screen.Forms does not support enumeration
begin
f := Screen.Forms[i];
if (f is T) then
begin
Result := f as T;
Exit;
end;
end;
end;
Except that fails to compile: 除了编译失败:
Result := nil; E2010 Incompatible types: 'T' and 'Pointer'
I can sorta see what's wrong. 我可以看看有什么不对劲。 It doesn't understand that T is a class (ie what if it was an
Integer
? Then it would absolutely be wrong to set it to nil
.) 它不明白T是一个类(即如果它是一个
Integer
呢?那么将它设置为nil
绝对是错误的。)
So i need to somehow give the compiler the hint of what type T
will be: 所以,我需要以某种方式给编译器是什么类型的提示
T
将是:
TScreenHelper = class helper for TScreen
public
function FindForm<T: TFormClass>: T;
end;
function TScreenHelper.FindForm<T: TFormClass>: T;
var
f: TForm;
i: Integer;
begin
Result := nil;
for i := 0 to Screen.FormCount-1 do //Screen.Forms does not support enumeration
begin
f := Screen.Forms[i];
if (f is T) then
begin
Result := f as T;
Exit;
end;
end;
end;
This new signature is confusing to call; 这个新的签名令人困惑! you no longer pass a desired type to the function.
您不再将所需类型传递给该函数。 Instead you now call a variation of the function that you want:
相反,你现在调用你想要的函数的变体:
frmContoso := Screen.FindForm<TfrmConsoto>();
But no matter; 但是不要紧; it's way of generics.
它是泛型的方式。
The syntax: 语法:
function FindForm<T: TFormClass>: T;
is not valid, as TFormClass
is not one of the allowed Delphi constraint types: 无效,因为
TFormClass
不是允许的Delphi约束类型之一:
Constraints in Generics
泛型中的约束
Specifying Generics with Constraints
使用约束指定泛型
Constraint items include:
约束项包括:
- Zero, one, or multiple interface types
零,一个或多个接口类型
- Zero or one class type
零或一类类型
- The reserved word "constructor", "class", or "record"
保留字“构造函数”,“类”或“记录”
(emphasis mine) (强调我的)
While i'm allowed one class type , i'm not passing a class type; 虽然我允许一种类型 ,但我没有传递类型; i'm passing a class of class type.
我正在传递一类课程类型。
So now i'm stuck. 所以现在我被卡住了。 In my attempt to save myself typing 25 characters, i've now blown an hour on the minutia of Delphi generics.
在我试图保存自己输入25个字符时,我现在已经在德尔福仿制药的细节上花了一个小时。
How do i genericize : 如何泛化 :
function FindForm(DesiredFormClass: TFormClass): TForm;
program Project2;
{$APPTYPE CONSOLE}
{$R *.res}
uses
System.SysUtils, Vcl.Forms;
type
TScreenHelperCore = class(TObject)
public
class function FindForm<T: TForm>: T;
end;
TfrmContoso = class(TForm)
public
end;
{ TScreenHelperCore }
class function TScreenHelperCore.FindForm<T: TForm>: T;
// \__[dcc32 Error] Project2.dpr(23): E2029 ',', ';' or '>' expected but ':' found
var
f: TForm;
i: Integer;
begin
Result := nil;
for i := 0 to Screen.FormCount-1 do //Screen.Forms does not support enumeration
begin
f := Screen.Forms[i];
if (f is T) then
begin
Result := f;
Exit;
end;
end;
end;
var
f: TfrmContoso;
begin
try
f := TScreenHelperCore.FindForm<TfrmContoso>;
if f = nil then
f := TfrmContoso.Create(nil);
f.ShowModal;
except
on E: Exception do
Writeln(E.ClassName, ': ', E.Message);
end;
end.
Your constraint is wrong. 你的约束是错误的。 Instead of
代替
function FindForm<T: TFormClass>: T;
you need 你需要
function FindForm<T: TForm>: T;
You are going to instantiate this generic type with TMyForm
rather than class of TMyForm
. 您将使用
TMyForm
而不是class of TMyForm
来实例化此泛型类型。
And you must only state the constraint in the declaration of the class and not in its implementation. 并且您必须仅在类的声明中声明约束,而不是在其实现中。 Here's a complete program that compiles:
这是一个完整的程序,编译:
{$APPTYPE CONSOLE}
uses
Vcl.Forms;
type
TScreenHelper = class helper for TScreen
public
function FindForm<T: TForm>: T;
end;
function TScreenHelper.FindForm<T>: T;
var
f: TForm;
i: Integer;
begin
for i := 0 to Screen.FormCount - 1 do
begin
f := Screen.Forms[i];
if (f is T) then
begin
Result := T(f);
Exit;
end;
end;
Result := nil;
end;
type
TMyForm = class(TForm)
end;
var
Form: TMyForm;
begin
Form := Screen.FindForm<TMyForm>;
end.
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.