2012-02-04 20 views
9

यह पहले से ही कई अलग-अलग तरीकों से पूछा गया है - लेकिन मुझे अभी तक मेरा जवाब नहीं मिला है।DELPHI: जेनेरिक और बहुरूपता

क्या कोई मेरे लिए कुछ चीजों को स्पष्ट कर सकता है। का उपयोग: डेल्फी XE2

मेरे पास काफी बड़ा आधार है जो मैं लगभग हर चीज़ के लिए उपयोग करता हूं। इसके साथ-साथ मेरे पास एक जेनेरिक सूची है - बेसलिस्ट।

Delarations इस तरह जाना:

TBaseObject = class 
... a lot of properties and methods ... 
end; 

TBaseList<T: TBaseObject> = class(TObjectList<T>) 
... some properties and methods ... 
end; 

मैं हाल ही में एक बहुत पुरानी TStringList से TBaseList घोषणा को बदलने के लिए वस्तुओं [] संपत्ति का उपयोग कर ... यह कभी अधिक बहुमुखी जेनेरिक्स सूची TObjectList की कोशिश की है।

लेकिन मैं कुछ समस्याओं में भाग लेता हूं। बेसयूनीट एक फ़ाइल है ... और हर बार जब मैं अपना बेसऑब्जेक्ट डाउन करता हूं तो मैं इसका पालन करने के लिए एक विशेष सूची भी बना देता हूं।

तो मैं जाने के लिए और की तरह कुछ करना होगा:

TCustomer = class(TBaseObject) 
... customer related stuff ... 
end; 

TCustomerList<T: TCustomer> = class(TBaseList<T>) 
... customer list specific stuff ... 
end; 

लेकिन अब मैं एक वस्तु की तरह एक सूची शामिल करने के लिए होगा - कि किसी भी वस्तु पकड़ कर सकते हैं। और मैंने सोचा कि मैं इसे इस

TControlObject = class(TBaseobject) 
    FGenList: TBaseList<TBaseObject>; 
end; 

की तरह कर सकता है के बाद से BaseList और BaseObject मेरी पदानुक्रम मैं मान लिया है कि इस तरह के एक सूची किसी भी सूची मैं के बारे में सोच सकता है धारण करने के लिए सक्षम हो जाएगा के शीर्ष पर है।

लेकिन मुझे लगता है कि इसे यहाँ मैं असफल है ... है एक TBaseList<TBaseobject> किसी भी तरह TCustomerList<TCustomer> ... यहां तक ​​कि अगर TCustomerList और TCustomer के लिए तुलनीय नहीं मेरी आधार का वंशज है है।

मैं आशा करता था कि नई वस्तुओं को स्थापित करने के लिए बेसलिस्ट में जेनेरिक का उपयोग करने में सक्षम हो। यानी। एक जनसंख्या विधि में T.Create का उपयोग कर।

var  
    aList : TBaseList<TBaseObject>; // used as a list parameter for methods 
    aPersonList : TPersonList<TPerson>; 
    aCustomerList : TCustomerList<TCustomer>; 
begin 
    aPersonList := TPersonList<TPerson>.Create; 
    aCustomerList := TCustomerList<TCustomer>.Create; 

    aList := aCustomerList; <-- this FAILS !! types not equal .. 

end; 

एक प्रक्रिया है कि सभी सूचियों के लिए आधार वर्ग संभालती कॉलिंग ही विफल रहता है: - मैं क्यों नहीं कर सकते

Base Unit; 
TBaseObject = class 
end; 
TBaseList<T:TBaseObject> = class(TObjectList<T>) 
end; 

CustomCustomer Unit; 
TCustomCustomer = class(TBaseObject) 
end; 
TCustomCustomerList<T:TCustomCustomer> = class(TBaseList<T>) 
end; 

Customer Unit; 
TCustomer = class(TCustomCustomer) 
end; 
TCustomerList<T:TCustomer> = class(TCustomCustomerList<T>) 
end; 

CustomPerson Unit; 
TCustomPerson = class(TBaseObject) 
end; 
TCustomPersonList<T:TCustomPerson> = class(TBaseList<T>) 
end; 

Person Unit; 
TPerson = class(TCustomPerson) 
end; 
TPersonList<T:TPerson> = class(TCustomPersonList<T>) 
end; 

ऊपर पदानुक्रम को देखते हुए:

यहाँ पूरा पदानुक्रम के उदाहरण है रास्ता ...

Procedure LogStuff(SomeList : TBaseList<TBaseObject>) 
begin 
    writeln(Format('No. Elements in list : %d',[SomeList.Count])); 
end; 

क्या कोई मुझे पंच कर सकता है और मुझे बता सकता है कि मैं यहां क्या कर रहा हूं?

+0

क्या आप कुछ कोड दे सकते हैं जहां आप इस अपमान की विफलता देखते हैं? मुझे यकीन नहीं है कि मुझे मिल गया है। –

+0

क्या आप एक TCustomerList को FGenList को असाइन करने का प्रयास कर रहे हैं, या आप FCenList में TCustomer को स्टोर करने का प्रयास कर रहे हैं? (ऐसा नहीं है कि मेरे पास जवाब होगा, लेकिन यह स्पष्ट कर सकता है कि आप क्या हासिल करने की कोशिश कर रहे हैं)। इसके अलावा, आप अलग-अलग सूची प्रकार क्यों घोषित कर रहे हैं? जेनेरिकों का मुद्दा यह है कि अब आपको टाइप सुरक्षा के लिए उनकी आवश्यकता नहीं है। टीएलआईस्ट । क्रेट टीएलिस्ट के साथ असंगत है। बनाएं। –

+0

@ यूवे और मार्जन: मैंने अपना प्रश्न संपादित कर लिया है ... काफी बड़ा हो गया - मुझे उम्मीद है कि इसका अभी भी संदर्भ है। लेकिन शायद यह अब और अधिक समझ में आता है? –

उत्तर

15

डेल्फी जेनेरिक कॉन्वर्सिस और contravariance का समर्थन नहीं करते हैं तो आप जो करने का प्रयास कर रहे हैं वह भाषा के वर्तमान वाक्यविन्यास के साथ संभव नहीं है। मेरा सुझाव है कि आपके पास निम्न ब्लॉग आलेखों का एक पठन है जो इस मामले को अधिक विस्तार से कवर करते हैं।

type 
    TBase = class; 
    TDerived = class(TBase); 
    TBaseList = TList<TBase>; 
    TDerivedList = TList<TDerived>; 
var 
    BaseList: TBaseList; 
    DerivedList: TDerivedList; 
... 
BaseList := TDerivedList;//does not compile 

डिजाइनरों आप द्वेष के कारण ऐसा करने से रोका नहीं है:

मूलरूप कि आप क्या करना प्रयास कर रहे हैं यह है। एक अच्छा कारण है। निम्न मानक उदाहरण पर विचार करें:

type 
    TAnimal = class; 
    TCat = class(TAnimal); 
    TPenguin = class(TAnimal); 

var 
    AnimalList: TList<TAnimal>; 
    CatList: TList<TCat>; 
    Penguin: TPenguin; 
... 
AnimalList := CatList;//does not compile because... 
AnimalList.Add(Penguin);//...of the danger of this 

जबकि यह एक एक TList<TAnimal> को TPenguin जोड़ने के लिए उचित है, वास्तविक सूची है कि AnimalList को संदर्भित करता है एक TList<TCat> है और एक पेंगुइन एक बिल्ली नहीं है।

और, यदि आप इसे अपने उदाहरण पदानुक्रम के संदर्भ में सोचना चाहते हैं, तो यहां कोड का एक उदाहरण है जो भाषा डिजाइन को औचित्य देता है।

aList := aCustomerList;//does not compile 
aList.Add(aCustomPerson); 
//this would add a TCustomPerson instance to a list containing 
//TCustomer instances, but a TCustomPerson is not a TCustomer 
+0

मेरे अंतर्ज्ञान को शब्दों को देने के लिए धन्यवाद। मैं "जानता था" इसे ऐसा कुछ होना था, लेकिन शब्दों या उदाहरणों के साथ नहीं आ सकता था। –

+5

आपके द्वारा प्रदान किए गए लिंक पढ़ने के बाद - मुझे कहना होगा ... धन्यवाद। यह जानकारी जेनेरिक के लिए मदद में शामिल की जानी चाहिए - विशेष रूप से TOBjectList! –

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