2014-02-10 8 views
1

목록이 TList<TForm>입니다. 나는 그것을 캐스팅 할 필요가 있으며이 같은 TList<TObject>로 사용TList에 TList <T:class>을 캐스팅합니다. <W:class>

procedure mainForm.testCast; 
var 
    listT: TList<TForm>; 
    listW: TList<TObject>; 
    obj: TObject; 
begin 
    listT := TList<TForm>.create; 
    listT.add(form1); 
    listT.add(form2); 

    listW := TList<TObject>(listT); // Casting is OK 

    // This works, but is this fine? 
    for obj in listW do 
    memo1.lines.add(obj.className); 

end; 

샘플은 예상대로 작동하지만 일반적인 목록 사이에 다음과 같이 캐스팅 할 수 괜찮아? 이로 인해 데이터 구조가 손상 될 수 있습니까? 루핑 (DoGetEnumerator) 목적과 일부 문자열 검사 즉 항목을 추가/제거하지 않기 위해서만 사용합니다.

실제 기능은 조금 더 복잡합니다. TValue에서 RTTI를 사용하여 listT에 대한 참조를 얻습니다. 주요 목표는 FMX.Forms을 내 유닛에 연결하는 것이 아닙니다.

업데이트 : Why are TGeneric<Base> and TGeneric<Descendant> incompatible types?

+0

괜찮 으면 작동하지만 조금 스케치입니다. 어쨌든 여기 캐스트를 사용해야 할 것 같지 않습니다. RTTI를 통해 열거 자에 연결할 수 있습니다. –

+0

'TForm'은'TObject'에서 파생되었고'TList '는 타입이 지정된 포인터의 일반적인 목록이므로 아무 것도 잘못되었습니다. 즉, 기본 클래스의 메서드를 사용합니다. –

+0

@LURD 나는 그것이 옳다고 생각하지 않는다. 'TList '은'TList '의 기본 클래스가 아닙니다. 'TList 은 TList '은'False'로 평가됩니다. 공통베이스는'TList '입니다. 그것에 대해 생각할 또 다른 방법. 기본 클래스의 메서드를 사용했다면 왜 캐스트가 필요할까요? –

답변

1

글쎄, 당신의 코드가 작동하지만, 내보기에 다소 의심스러운 것입니다.

TList<TForm>.InheritsFrom(TList<TObject>) 

이 거짓이므로 단순히 캐스트를 넣는 것이 잘못되었습니다. 따라서 TList<TForm> 개체는 TList<TObject>이 아닙니다. 그렇다면 캐스팅은 필요하지 않을 것입니다.

이것은 델파이의 제네릭 형식이 불변하므로 그렇게합니다. 자세한 내용은 여기에서 찾을 수 있습니다 : Why is a class implementing an interface not compatible with the interface type when used in generics?

당신이 어떤 어려움 디자이너가 잠시 코드에 listW.Add(TObject.Create)를 작성하는 효과를 고려, 일반적인 유형은 불변 만든 이유는 이해가있는 경우. 유형 TList<TForm>의 진정한 기본 대상에 어떤 의미가 있는지 생각해보십시오.

그래서이 언어는 아무 것도 약속하지 않습니다. 귀하는 보증의 범위를 벗어나지 않습니다. 이 두 가지 관련없는 유형의 구현은 코드가 작동하기에 충분히 호환됩니다. 그러나 그것은 실제로 구현의 사고입니다.

이미 RTTI를 사용하고 있으므로 RTTI로 목록을 반복하는 것이 좋습니다. RTTI를 사용하여 GetEnumerator 등으로 전화 할 수 있습니다. 그렇게하면 객체의 실제 메소드를 호출 할 수 있습니다.

+0

@ David-Heffernan! 내 목표는 RTTI를 사용하여 Form의 자식을 열거하는 것입니다. 열거자는 TEnumerator 을 반환하지만 FMX.Types를 내 장치에 포함하고 싶지 않습니다. 그래서 위의 질문을 일으키는 TEnumerator 과 같은 결과를 전달하고 싶습니다. –

+1

구체적인 유형으로 캐스트하려면 ** not **가 필요합니다. 당신은 전적으로 RTTI의 세계에 충실해야합니다. 코드는 작동하지만 구현 세부 사항에 의존합니다. –

+0

"RTTI의 세계에 전적으로 매달릴 필요가 있습니다."- 좋은 지적 :) –