2009-11-19 4 views
2

이전 post을 기반으로 다음 코드를 작성했습니다. 이 게시물의 자세한 내용을 용서해주십시오. 모든 당사자가 전체 코드를 테스트하고 의견을 제시 할 수 있도록하는 것이 더 바람직하다고 생각합니다. 현실 세계에서 TIntTStr의 생성자뿐만 아니라 Low, High: integerLength: integer 매개 변수를 활용하는 것이델파이 : generics and 'is'-operator problem

program sandbox; 
{$APPTYPE CONSOLE} 

uses 
    SysUtils, 
    Generics.Collections; 

type 
    TDataType = class 
    // Stuff common to TInt and TStr 
    end; 

    TInt = class(TDataType) 
    FValue: integer; 
    constructor Create(Value, Low, High: integer); 
    end; 

    TStr = class(TDataType) 
    FValue: string; 
    constructor Create(Value: string; Length: integer); 
    end; 

    TSomeClass = class 
    FIntList: TList<TInt>; 
    FStrList: TList<TStr>; 
    procedure AddToList<T: TDataType>(Element: T); 
    constructor Create(); 
    procedure Free(); 
    end; 

constructor TInt.Create(Value, Low, High: Integer); 
begin 
    inherited Create(); 
    FValue := Value; 
end; 

constructor TStr.Create(Value: string; Length: Integer); 
begin 
    inherited Create(); 
    FValue := Value; 
end; 

procedure TSomeClass.AddToList<T>(Element: T); 
begin 
    if TObject(Element) is TInt then 
    FIntList.Add(Element) 
    else if TObject(Element) is TStr then 
    FStrList.Add(Element); 
end; 

constructor TSomeClass.Create(); 
begin 
    inherited; 
    FIntList := TList<TInt>.Create(); 
    FStrList := TList<TStr>.Create(); 
end; 

procedure TSomeClass.Free(); 
var 
    SomeIntItem: TInt; 
    SomeStrItem: TStr; 
begin 
    for SomeIntItem in FIntList do begin 
    SomeIntItem.Free(); 
    end; 

    for SomeStrItem in FStrList do begin 
    SomeStrItem.Free; 
    end; 

    FIntList.Free(); 
    FStrList.Free(); 
end; 

var 
    Inst: TSomeClass; 

begin 
    try 
    { TODO -oUser -cConsole Main : Insert code here } 

    Inst := TSomeClass.Create; 
    Inst.AddToList(TInt.Create(100, 0, 101)); 
    Inst.AddToList(TStr.Create('Test', 10)); 
    Inst.Free; 

    except 
    on E:Exception do 
    Writeln(E.Classname, ': ', E.Message); 
    end; 
end. 

참고. if TObject(Element) is TInt then에 "E2089 Invalid typecast"가 있고, Delphi 2009를 실행하는 else if TObject(Element) is TStr then에 있습니다. 왜 이런 일이 발생하는지 알고 계십니까?

편집 : TIntTStr은 아마도 10-20 개의 다른 유형 중 2 가지 일뿐입니다. 그렇지 않으면 작업에 대한 공구 인 이 과부하됩니다. :)

+0

귀하의 선언과 AddToList의 구현은 다르다. 제네릭에 대해서는 충분히 알지 못하지만 정기적 인 파스칼에 대해서는 잘못되었습니다. –

+0

안녕 Lieven! "프로 시저 AddToList (요소 : T)"와 달리 "프로 시저 TSomeClass.AddToList (요소 : T)"구현을 언급하고 있다고 생각하십니까? 그렇다면 귀하의 의견에 대한 응답은 RAD Studio가 실제 구현에 대한 제약을 원하지 않는다는 것입니다. – conciliator

+0

아, 알겠습니다. 아직 가장 명확한 것은 제네릭에 아직 들어 있지 않은 사람들을위한 것입니다. 그것을 지워 줘서 고마워. –

답변

7

디자인을 다시 말하십시오.

procedure Add (SomeString : TString); overload; 
procedure Add (SomeInt : TInt); overload; 

을 아니면 해당 매개 변수에 is를 사용하여, 다형성 Gamecat 제안 일을 사용하고 단지 매개 변수로 기본 유형을 전달하려면 : 당신은 다음과 같이 제네릭 형식 매개 변수 대신에 과부하를 사용할 수 있습니다

procedure Add (Element : TDataType);   

Rob이 이전 질문에 대한 의견에서 지적한 것처럼 Rob은 두 가지 유형 만 허용하고 실제 유형을 기반으로하는 조건을 사용하면 실제로는 일반적이지 않습니다. 따라서 제네릭은 잘못된 도구 일 수 있습니다.

희망이 있습니다.

+0

컴파일러 버그가 없습니다. 그것의 형변환 ;-) 누락. 그러나 잘못된 도구 설명에 동의합니다. –

+0

질문을 잘못 읽었습니다. 나는 나의 대답을 업데이트했다. – jpfollenius

+0

감사합니다. Smasher! 나는 처음부터 TInt와 TStr이 10 가지 이상의 다른 유형을 동반하게 될 것이라고 지적했음을 알았습니다. TypeInfo() 메서드를 인식하지 못했습니다. 그래서 +1하십시오! :) – conciliator

3

제네릭에는 문제가 없습니다. TDataType을 TInt 또는 TStr이 필요한 목록에 추가합니다.

procedure TSomeClass.AddToList<T>(Element: T); 
begin 
    if TObject(Element) is TInt then 
    FIntList.Add(TInt(Element)) 
    else if TObject(Element) is TStr then 
    FStrList.Add(TStr(Element)); 
end; 

문제를 해결합니다.

는하지만 사용하지 이유 :

procedure TSomeClass.AddToList(Element: TDataType); 
begin 
    if Element is TInt then 
    FIntList.Add(TInt(Element)) 
    else if Element is TStr then 
    FStrList.Add(TStr(Element)); 
end; 
+0

+1 분명히 내가했던 것보다 더 좋은 질문을 읽습니다. – jpfollenius

+0

고마워, Gamecat! 마지막 예제는 멋지게 컴파일됩니다. 그러나 첫 번째 예제 (T : TDataType, T : 클래스 및 빈 제약 조건 시도)를 사용하여 여전히 형식 변환 오류가 발생합니다. 컴파일 했니? – conciliator

+0

@Gamecat : 아마도 처음에는 명확하지 않았습니까? "TObject (Element)가 TInt이면"및 "TObject (Element)가 TStr이면 else"라는 문장에서 타입 변환이 실패합니다. 왜 그런지 알고 있습니까? – conciliator