2009-05-12 5 views
6

델파이에서 RTTI (또는 다른 것)를 사용하여 클래스가 추상으로 선언되었는지 확인할 수 있습니까? 같은 뭔가 다음 TypInfo 장치를 통해Delphi 클래스가 추상으로 선언되었는지 확인하는 방법은 무엇입니까?

TMyAbstractClass = class abstract(TObject) 
    // ... 
end; 

... 

if IsAbstract(TMyAbstractClass.ClassInfo) then 
    ShowMessage('Yeah') 
else 
    ShowMessage('Computer says no...'); 
+0

이 질문에 대한 답변은 도움이 될 수 있습니다. http://stackoverflow.com/questions/791004/how-can-i-detect-if-a-delphi-class-has-a-virtual-constructor – RobS

답변

0

빠른 보면 도움이 아무것도를 설정하지 않습니다. "추상적 인 클래스"의 개념은 순전히 컴파일러의 이익이라고 생각합니다. 이 클래스의 인스턴스 생성은 없으며 런타임에만 아무 것도하지 않으므로 RTTI를 기록 할 필요가 없습니다.

왜 당신은 어쨌든 호기심에서 이것을 찾으려고합니까?

+0

공통 조상과 함께 다른 classtype (TCollectionItem)을 포함 할 수있는 TCollection 파생 클래스가 있습니다. 구체적으로는 다른 유형의 열을 포함하는 그리드 열 컬렉션입니다. 그리고 지금은 (TClassFinder를 사용하여) 등록 된 열 유형을 추가 할 수있는 designtime 컬렉션 편집기를 만들고 싶습니다.하지만이 편집기에서 abtract 클래스를 원하지 않습니다. 내 추상 클래스의 이름은 TCustom *이므로 지금은 클래스 이름을 사용하여 필터링하고 있습니다. – mrMoo

+0

따라서, 당신의 문제는 추상적 인 클래스를 탐지하는 방법에 관한 것이 아닙니다. 문제는 유효한 "열 유형"목록을 얻는 것입니다. 쉬운 해결책은 유효한 열 유형 인 클래스 만 등록하는 것입니다. 우선 추상 클래스를 등록하지 마십시오. 클래스를 등록하는 유일한 이유는 이름으로 검색하고 인스턴스화 할 수 있기 때문입니다. 인스턴스화 된 적이없는 클래스는 등록하지 마십시오. VCL은 자신 만의 "사용자 정의"기본 클래스도 등록하지 않습니다. –

+0

예 사실, 문제는 필자가 제안한 것처럼 "유효한"클래스 만 등록한다는 것이지만, Delphi는 자동으로 부모 클래스도 등록합니다. RegisterClass (TButton)을 사용하여 TButton을 등록하면 Delphi는 TCustomButton, TButtonControl 등을 등록합니다.어쨌든 아주 추상적 인 방법에 대한 귀하의 게시물을 주셔서 감사합니다,하지만 내 질문에 대한 올바른 대답은 "아니오"라고 생각합니다 – mrMoo

6

내가 직접 귀하의 질문에 대답 할만큼 최근의 버전을 가지고 있지만, 그것은 클래스가 추상적인지하지 정말 문제를 않는다는 것을 명심하지 않습니다. 컴파일러가 클래스에서 직접 생성자를 호출하지 못하도록합니다. 클래스 참조를 클래스 참조 변수에 넣으면 컴파일러에서 변수에 대해 생성자를 호출 할 수있게하고 실행시에는 인스턴스화 할 수없는 클래스의 인스턴스를 갖게됩니다. 정말 중요한 무엇

var 
    c: TClass; 
    o: TObject; 
begin 
    c := TMyAbstractClass; 
    o := c.Create; 
    Assert(o is TMyAbstractClass); 
end; 

클래스는 모든 추상 메소드이 있는지 여부를 입니다. 그 사실을 쉽게 확인할 수 있습니다. 클래스의 VMT를 살펴보십시오. System._AbstractError에 대한 포인터가 포함 된 가상 메서드 슬롯은 추상 메서드입니다. 까다로운 부분은 기록 할 수 없기 때문에 검사 ​​할 가상 메소드 슬롯의 수를 아는 것입니다. Allen Bauer demonstrated how to do that에 대한 대답은 another question이지만 Mason Wheeler의 의견에 따르면 더 큰 값을 반환 할 수 있다고 지적합니다. 그는 GetVirtualMethodCount 함수를 JCL에서 언급 했으므로 사용자 정의 가상 메서드를 더 정확하게 계산해야합니다. 다음 추상 클래스는 더 추상적 인 방법이없는 경우

function HasAbstractMethods(c: TClass): Boolean; 
var 
    i: Integer; 
begin 
    Result := True; 
    for i := 0 to Pred(GetVirtualMethodCount(c)) do 
    if GetVirtualMethod(c, i) = @_AbstractError then 
     exit; 
    Result := False; 
end; 

, 어떻게 추상적 정말 할 수 있습니다 다음 JCL에서 또한 그 기능과 GetVirtualMethod를 사용하여, 우리는이 기능을 얻을? 개발자가 인스턴스를 만들지 못하게하려면 추상으로 표시되어야하지만, 실제로 원한다면 어쨌든 인스턴스를 만들 수 있으므로 추상 클래스를 표시하는 것은 실제로 사용에 대한 실제 제한보다 더 많은 경고입니다.

+0

불행히도, 일부 테스트를했을 때 Allen의 알고리즘은 모든 경우에 작동하지 않는 것으로 나타났습니다. 나는 그것을 알아낼 수 있다면 그 질문을 조금 들여다보고 그 문제에 대한 수정을 게시 할 것입니다. –

+0

분명히 다른 것들도 그 이름 앞에 붙일 수 있습니다. Allen의 알고리즘 대신 JCLSysUtils.GetVirtualMethodCount를 사용해보십시오.이 메소드는 GetVirtualMethod와 같은 JCL 유닛에 편리하게 배치됩니다. –

+0

실제로. JCL 버전은 VMT의 다른 모든 포인터를 검사하고 첫 번째 가상 메소드와 클래스 이름 사이에 발생하는 포인터가 있으면 가상 메소드의 범위로 간주되는 윈도우를 "축소"합니다. –