2013-02-27 17 views
7

Rozważmy następujący fragment kodu:Delphi: OleVariant i rodzajowych

type 
    MyIntf = interface 
    procedure Work(param: OleVariant); 
    end; 

    MyClass<T> = class 
    procedure MyWork(param: T); 
    end; 

var 
    intf: MyIntf; 

procedure MyClass<T>.MyWork(param: T); 
begin 
    //compiler error: E2010 Incompatible types: 'OleVariant' and 'T' 
    intf.Work(param); 
end; 

to zawiedzie skompilować z komunikatem o błędzie, jak wskazano powyżej. Jak mogę zadzwonić do funkcji Work z mojej klasy ogólnej?

+2

Dlaczego oh dlaczego jest to w porządku pytanie zbliżają głosów? Czy wyborcy nawet patrzą na to, nad czym głosują? –

+0

Nie martw się, zawsze możemy ponownie otworzyć :-) – Johan

+3

@Johan Nie powinniśmy tego robić. Te kolejki przeglądania w SO są po prostu głupie. –

Odpowiedz

8

Twój kod nie kompiluje się, ponieważ kompilator nie może zagwarantować podczas kompilacji klasy ogólnej, że istnieje możliwość zamiany na wszystkie możliwe T.

W obliczu

intf.Work(param); 

w sposób rodzajowy kompilator musi wiedzieć, jak konwertować param do OleVariant. I nie może tego zrobić. Jest to jedno z ograniczeń generycznych w porównaniu do szablonów.


Najprostszym rozwiązaniem dla ciebie jest zrobić konwersję przy starcie z pomocą TValue z jednostki Rtti.

procedure MyClass<T>.MyWork(param: T); 
begin 
    intf.Work(TValue.From<T>(param).AsVariant); 
end; 

A oto przykładowy program testów w celu wykazania, że ​​TValue spełnia swoje zadanie:

program SO15113162; 
{$APPTYPE CONSOLE} 

uses 
    Rtti; 

procedure Work(param: OleVariant); 
begin 
    Writeln(param); 
end; 

type 
    MyClass<T> = class 
    class procedure MyWork(param: T); 
    end; 

class procedure MyClass<T>.MyWork(param: T); 
begin 
    Work(TValue.From<T>(param).AsVariant); 
end; 

begin 
    MyClass<Double>.MyWork(2.4); 
    MyClass<string>.MyWork('hello'); 
    MyClass<Integer>.MyWork(-666); 
    Readln; 
end. 

Wyjście

 
2.4 
hello 
-666