2014-07-17 2 views
4

그래서 같은 일반적인 기록을 선언하고 싶습니다 :익명 메소드 유형에 어떤 일반 제약 조건을 사용합니까?

type 
    TMyDelegate<T: constraint> = record 
    private 
    fDelegate: T; 
    public 
    class operator Implicit(a: T): TMyDelegate; 
    class operator Implicit(A: TMyDelegate: T); 
    end; 

내가 reference to procedure/functionT을 제한하고 싶습니다. (가능한 한 많이).

나는이 시도했지만,이 컴파일되지 않습니다 :

[dcc32 Error] Project3.dpr(39): E2514 Type parameter 'T' must support interface 'TProc2'

의 (목록에 제네릭 형식을 제한 할 수있는 방법이 있나요 :

program Project3; 

{$APPTYPE CONSOLE} 
{$R *.res} 

uses 
    System.SysUtils; 

type 

    TProc1 = reference to procedure(a: Integer); 
    TProc2 = reference to procedure(b: TObject); 

    TTest<T: TProc1, TProc2> = record 
    private 
    fData: T; 
    public 
    class operator Implicit(a: T): TTest<T>; 
    class operator Implicit(a: TTest<T>): T; 
    end; 

    { TTest<T> } 

class operator TTest<T>.Implicit(a: T): TTest<T>; 
begin 
    Result.fData:= a; 
end; 

class operator TTest<T>.Implicit(a: TTest<T>): T; 
begin 
    Result:= a.fData; 
end; 

var 
    Delegate1: TProc1; 
    Delegate2: TProc2; 

var 
    MyTest1: TTest<TProc1>; <<-- error 
    MyTest2: TTest<TProc2>; 

begin 
    MyTest1:= 
    procedure(a: Integer) 
    begin 
     WriteLn(IntToStr(a)); 
    end; 
end. 

이 컴파일 에러 제공) 익명 형식?

답변

3

이러한 제약 조건을 지정할 방법이 없습니다. 가능한 제약 조건은 다음과 같습니다.

  • 값 유형.
  • 클래스, 특정 조상에서 파생됩니다.
  • 인터페이스, 특정 조상으로부터 파생되었습니다.
  • 매개 변수없는 생성자.

이이 문서에 포함되어 http://docwiki.embarcadero.com/RADStudio/en/Constraints_in_Generics

은 무엇 설명서를 명확하게하지 않는 것은 그 기준 절차의 유형 인터페이스로 계산이다. 그렇다면 제네릭 형식이 해당 제약 조건과 함께 컴파일됩니다. 그러나 이것은 결코 당신에게 아무 소용이 없습니다. 참조 프로 시저 유형에는 상속이 없으므로 특정 참조 절차 유형 제약 조건을 충족시킬 수있는 유일한 방법은 특정 유형의 것입니다.

사실 유형을 인스턴스화 할 수 없습니다. 제약

T: TProc1, TProc2 

T가 그 기준 절차 인터페이스 모두를 지원하도록 지정하기 때문이다. 그리고 아무 것도 그것을 할 수 없습니다. 아무것도 TProc1TProc2을 동시에 지원할 수 없습니다.

+0

제약 조건이 OR'ed가 아닌 AND'ed 인 것을 잊어 버렸습니다. – Johan

+0

참조 절차 제약 조건은 사실 전혀 쓸모가 없습니다. –

+0

요구 사항을 충족하는 THack = class (TInterfacedObject, TProc1, TProc2) 클래스를 만들 수 있습니다. 어떤 용도로 사용할 지 모르겠지만 컴파일 할 수 있다고 생각합니다. – Johan

5

다윗의 정답하지만이 같은 주위의 작품으로 도움이 될 수 GrayMatter 다윗에

program Project51; 

{$APPTYPE CONSOLE} 
{$R *.res} 

uses 
    System.SysUtils; 

type 
    TTest<T> = record 
    type 
    TProcT = reference to procedure(a: T); 
    private 
    fData: TProcT; 
    public 
    class operator Implicit(a: TProcT): TTest<T>; 
    class operator Implicit(a: TTest<T>): TProcT; 
    end; 

    { TTest<T> } 

class operator TTest<T>.Implicit(a: TProcT): TTest<T>; 
begin 
    Result.fData:= a; 
end; 

class operator TTest<T>.Implicit(a: TTest<T>): TProcT; 
begin 
    Result:= a.fData; 
end; 

var 
    MyTest1: TTest<Integer>; 
    MyTest2: TTest<TObject>; 

begin 
    MyTest1:= 
    procedure(a: Integer) 
    begin 
     WriteLn(IntToStr(a)); 
    end; 
    MyTest2:= 
    procedure(a: TObject) 
    begin 
     WriteLn(a.ClassName); 
    end; 
end. 
+0

@GreyMatter, 내 문제를 해결하는 데 시간이 좀 걸립니다. 거기에서 해결책을 볼 수 있습니다. – Johan

+0

+1 well ..... ..... –

+1

System.Sysutils가 'TProc = 프로 시저 (Arg1 : T)에 대한 참조'를 선언했다는 사실을 감안할 때 직접 선언하는 대신 사용할 수 있습니다. –

2

덕분에 나는이 문제에 대한 해결책을 마련했습니다를.

해결책은 익명 프로 시저를 제약 조건에 맞게 재정의하는 것입니다.

다음 기능이 정의됩니다.

TA = reference to procedure(const &In, &Out: TArray<TOmniValue>); 
TB = reference to procedure(const &In, &Out: TArray<IOmniBlockingCollection>); 
TC = ..... 

트릭과 같이 방법을 재정의하는 것입니다

program Project3; 

{$APPTYPE CONSOLE} 
{$R *.res} 

uses 
    System.SysUtils; 

type 
    IData<Tin, Tout> = interface 
    ['{D2132F82-CAA9-4F90-83A9-9EFD6221ABE2}'] 
    function GetInput: TArray<TIn>; 
    function GetOutput: TArray<Tout>; 
    end; 

    TData<TIn, TOut> = class(TInterfacedObject, IData<Tin, Tout>) 
    private 
    fInput: TArray<Tin>; 
    fOutput: TArray<Tout>; 
    public 
    constructor Create(const input: TArray<TIn>; const output: TArray<TOut>); 
    function GetInput: TArray<Tin>; 
    function GetOutput: TArray<Tout>; 
    end; 

    TDelegate<Tin, Tout> = reference to procedure(const Data: IData<TIn, TOut>); 

{ TSimpleData } 

constructor TData<TIn, TOut>.Create(const input: TArray<TIn>; 
    const output: TArray<TOut>); 
begin 
    finput:= input; 
    foutput:= output; 
end; 

function TData<Tin, Tout>.GetInput: TArray<Tin>; 
begin 
    Result:= fInput; 
end; 

function TData<Tin, Tout>.GetOutput: TArray<TOut>; 
begin 
    Result:= fOutput; 
end; 

var 
    IntegerDelegate: TDelegate<Integer, Integer>; 
    input, output: TArray<Integer>; 
    i: Integer; 
    Data: TData<Integer, Integer>; 

begin 
    IntegerDelegate:= procedure(const Data: IData<Integer, Integer>) 
    var 
    i: Integer; 
    input: TArray<Integer>; 
    begin 
    input:= Data.GetInput; 
    for i:= 0 to High(input) do begin 
     Data.GetOutput[i]:= input[i]+10; 
    end; 
    end; 
    SetLength(input,10); 
    SetLength(output, Length(input)); 
    for i:= Low(input) to High(input) do begin 
    input[i]:= i; 
    end; 
    Data:= TData<Integer, Integer>.Create(input, output); 
    IntegerDelegate(Data); 
    for i in output do Writeln(i); 
    Readln; 
end. 

지금 허용 된 유형 (자세한 이하)의 위임을 제한 할 수 있습니다.

관련 문제