2011-11-29 20 views
10

मैं स्रोत कोड के बिना एक बहुत बड़ी डेल्फी तृतीय पक्ष लाइब्रेरी का उपयोग कर रहा हूं, इस पुस्तकालय में अमूर्त तरीकों के साथ कई कक्षाएं हैं। मुझे यह निर्धारित करने की आवश्यकता है कि EAbstractError: Abstract Error से बचने के लिए रनटाइम में एक descendant क्लास द्वारा एक अपवर्तक विधि लागू की जाती है और उपयोगकर्ता को कस्टम संदेश दिखाती है या इसके बजाय किसी अन्य वर्ग का उपयोग करती है।मैं कैसे निर्धारित कर सकता हूं कि एक सार विधि लागू की गई है या नहीं?

उदाहरण के लिए इस कोड में मैं रनटाइम में जांचना चाहता हूं यदि MyAbstractMethod लागू किया गया है।

type 
    TMyBaseClass = class 
    public 
    procedure MyAbstractMethod; virtual; abstract; 
    end; 

    TDescendantBase = class(TMyBaseClass) 
    public 
    end; 

    TChild = class(TDescendantBase) 
    public 
    procedure MyAbstractMethod; override; 
    end; 

    TChild2 = class(TDescendantBase) 
    end; 

मैं कैसे निर्धारित कर सकते हैं एक सार विधि क्रम में एक वंशज कक्षा में कार्यान्वित किया जाता है?

उत्तर

10

आप आरटीआई का उपयोग कर सकते हैं, GetDeclaredMethods फ़ंक्शन प्रतिबिंबित (वर्तमान) प्रकार में घोषित सभी विधियों की एक सूची प्राप्त करता है। तो आप जांच सकते हैं कि विधि इस फ़ंक्शन द्वारा लौटाई गई सूची में मौजूद है या नहीं।

function MethodIsImplemented(const AClass:TClass;MethodName : string): Boolean; 
var 
    m : TRttiMethod; 
begin 
    Result := False; 
    for m in TRttiContext.Create.GetType(AClass.ClassInfo).GetDeclaredMethods do 
    begin 
    Result := CompareText(m.Name, MethodName)=0; 
    if Result then 
    break; 
    end; 
end; 

या आप TRttiMethod की Parent.Name संपत्ति की तुलना और अगर वर्तमान वर्ग के नाम के साथ मैच देख सकते हैं। VCL स्रोत कोड में TStream.Seek() विधि के क्रियान्वयन पर

function MethodIsImplemented(const AClass:TClass;MethodName : string): Boolean; 
var 
    m : TRttiMethod; 
begin 
    Result := False; 
    m:=TRttiContext.Create.GetType(AClass.ClassInfo).GetMethod(MethodName); 
    if m<>nil then 
    Result:=CompareText(AClass.ClassName,m.Parent.Name)=0; 
end; 
4

देखो। यह एक समान प्रकार की अवरोध-ओवर्रिडेन चेक करता है जैसा आप ढूंढ रहे हैं, और इसमें TRttiContext ऐसा करने के लिए लुकअप शामिल नहीं है, केवल अपने माता-पिता/बाल vtable प्रविष्टियों के माध्यम से एक साधारण पाश।

4
function ImplementsAbstractMethod(AObj: TMyBaseClass): Boolean; 
type 
    TAbstractMethod = procedure of object; 
var 
    BaseClass: TClass; 
    BaseImpl, Impl: TAbstractMethod; 
begin 
    BaseClass := TMyBaseClass; 
    BaseImpl := TMyBaseClass(@BaseClass).MyAbstractMethod; 
    Impl := AObj.MyAbstractMethod; 
    Result := TMethod(Impl).Code <> TMethod(BaseImpl).Code; 
end; 
+0

धन्यवाद, लेकिन अगर इस तरह से उपयोग किया जाता है तो मुझे प्रत्येक वर्ग के प्रकार के लिए एक फ़ंक्शन को लागू करने की आवश्यकता होती है और मैं एक और सामान्य समाधान पसंद करता हूं। – Salvador

+0

मुझे यकीन नहीं है कि आपका कोड सही है या नहीं। 'कार्यान्वयन सारणी विधि (TChild2.Create) 'सच हो जाएगा, लेकिन न तो' TChild2', न ही 'TDescendantBase' ने' TMyBaseClass' के सार' MyAbstractMethod' को ओवरराइड कर दिया है। http://pastebin.com/JufNPJkg –

+0

@rinntech: सिर के लिए धन्यवाद। मैंने सही कोड के साथ जवाब अद्यतन किया है। –

संबंधित मुद्दे

 संबंधित मुद्दे