2012-04-08 8 views
10

में एक सामान्य वर्ग में एक प्रकार का उपनाम बनाना संभव है, मैं एक सामान्य वर्ग के लिए कक्षा प्रकार (प्रकार उपनाम) को परिभाषित करना चाहता हूं। मैं ऐसा करना चाहता हूं ताकि यूनिट बी के उपयोगकर्ताओं को यूनिट ए का उपयोग किये बिना टीएमटी टाइप तक पहुंच हो। मैं इस तरह इकाइयां हैं:क्या डेल्फी

unit a; 
interface 
type 
    TMyNormalObject = class 
    FData: Integer; 
    end; 
    TMyType<T> = class 
    FData: <T>; 
    end; 
implementation 
end. 

unit b; 
interface 
type 
    TMyNormalObject = a.TMyNormalObject; // works 
    TMyType<T> = a.TMyType<T>; // E2508 type parameters not allowed on this type 
implementation 
end. 

मैं पहले से ही एक संभावित समाधान पाया जो मैं क्योंकि यह कीड़े मुश्किल लागू कर सकते हैं पसंद नहीं है:

TMyType<T> = class(a.TMyType<T>); 

इस दृष्टिकोण के साथ समस्या यह है कि यह एक नए वर्ग के प्रकार का परिचय देता है और एक। टीटी टाइप टाइप बीटीएम टाइप नहीं है (जबकि ए। टीएम नॉर्मल क्लास एक बीटीएमनोर्मल क्लास है और इसके विपरीत - वे एक ही कक्षा का जिक्र कर रहे हैं)।

+0

यह संभव के 'TMyType ' सभी उपयोगकर्ताओं इकाई ख से उल्लेख करने के लिए के लिए नहीं है? उस स्थिति में आपका कामकाज संभव हो सकता है। –

+1

क्यों इंटरफ़ेस नहीं बनाते और अपने उपयोगकर्ताओं को इसका खुलासा नहीं करते? – whosrdaddy

उत्तर

10

यह वर्तमान में एक सामान्य वर्ग के लिए कक्षा प्रकार घोषित करने के लिए संभव नहीं है।

अधिक जानकारी के लिए QC76605 देखें। इसके अलावा नीचे अपडेट भी।

उदाहरण:

TMyClass<T> = class 
end; 
TMyClassClass<T> = class of TMyClass<T>; //E2508 type parameters not allowed on this type 

वैकल्पिक हल है कि इस तरह दिखता है प्रस्तुत किया है:

TMyIntClass = TMyType<Integer>; 
TMyIntClassClass = Class of TMyIntClass; 

लेकिन जैसे टिप्पणी की, कि, जेनरिक के पूरे विचार को हराने के बाद से वर्ग होना जरूरी होगा प्रत्येक सामान्य तत्काल के लिए subclassed।

यहां सामान्य प्रकार के एक विशेष उप-वर्ग को उत्पन्न करने के समान कार्यवाही का एक लिंक भी है: derive-from-specialized-generic-types। इस मामले में यह इस तरह दिखेगा:

TMySpecialClass = Class(TMyType<Integer>); 

अद्यतन:

वैकल्पिक हल आर एम द्वारा प्रस्तावित:

:

TMyType<T> = class(a.TMyType<T>); 

टाइप सुरक्षा का उपयोग कर निम्नलिखित योजना कार्यान्वित किया जा सकता

unit Unita; 
interface 
type 
    TMyType<T> = class 
    Constructor Create; 
    end; 

implementation 

uses 
    Unitb; 

constructor TMyType<T>.Create; 
begin 
    Inherited Create; 
    //WriteLn(Self.QualifiedClassName,' ',Unitb.TMyType<T>.QualifiedClassName); 
    Assert(Self.QualifiedClassName = Unitb.TMyType<T>.QualifiedClassName); 
end; 

end. 

unit Unitb; 

interface 

uses Unita; 

type 
    TMyType<T> = class(Unita.TMyType<T>); 
implementation 
end. 

Project Test; 
{$APPTYPE CONSOLE}  
uses 
    System.SysUtils, 
    Unita in 'Unita.pas', 
    Unitb in 'Unitb.pas'; 

var 
    t1 : Unita.TMyType<Integer>; 
    t2 : Unitb.TMyType<Integer>; 
    t3 : TMyType<Integer>;  
begin 
    try 
    //t1 := Unita.TMyType<Integer>.Create; //Exception EAssertionFailed !! 
    t2 := Unitb.TMyType<Integer>.Create; 
    t3 := TMyType<Integer>.Create; 
    ReadLn; 
    finally 
    //t1.Free; 
    t2.Free; 
    t3.Free; 
    end; 
end. 

जब सामान्य वर्ग बनाने, एक परीक्षण जांचने के लिए कि बनाया वर्ग प्रकार इकाई ख में घोषित से ली गई है बना है। इस प्रकार इकाई से इस वर्ग को बनाने के सभी प्रयासों का पता लगाया गया है।

अद्यतन 2:

बस स्पष्ट होना, एक सामान्य वर्ग के लिए एक संदर्भ, "class of type<T>" नहीं संभव है, लेकिन एक सामान्य वर्ग की एक प्रति ठीक है।

+0

हाय लू आरडी, धन्यवाद लेकिन क्षमा करें, सवाल व्हायरन द्वारा संपादित किया गया है और उसने इसका अर्थ बदल दिया है। मैंने इसे वापस बदल दिया। मैं जेनेरिक प्रकार के लिए एक प्रकार के उपनाम घोषित करना चाहता हूं, न कि कक्षा प्रकार। मुझे पता है कि मेरा कामकाज सीमा के साथ काम करता है। –

+1

ठीक है, मैं समझता हूं। लेकिन किसी भी अस्पष्टता से बचने के लिए आपको "टाइप उपनाम" को ["' वर्ग संदर्भ' "] (http://docwiki.embarcadero.com/RADStudio/en/Class_References) में दोहराया जाना चाहिए। –

+0

वैसे मैं कक्षा में एक प्रकार के उपनाम की तलाश में हूं, न कि कक्षा संदर्भ। –

0

चूंकि जेनेरिक क्लास के लिए "टाइप उपनाम" घोषित करना संभव नहीं है, तो यहां interface का उपयोग करके एक समाधान है।

unit UnitA; 

interface 

Uses UnitB; 

type 
    TMyType<T> = class(TInterfacedObject,ITMyType<T>) 
    FData : T; 
    Constructor Create(aV : T); 
    end; 

implementation 

constructor TMyType<T>.Create(aV : T); 
begin 
    Inherited Create; 
    FData := aV; 
    WriteLn(Self.QualifiedClassName); 
end; 

end. 

unit UnitB; 

interface 

type 
    ITMyType<T> = Interface 
    End; 

implementation 

end. 

program Test; 
{$APPTYPE CONSOLE} 
uses 
    UnitA in 'UnitA.pas', 
    UnitB in 'UnitB.pas'; 

var 
    it1 : ITMyType<Integer>; 
begin 
    it1:= TMyType<Integer>.Create(1); 
    ReadLn; 
end.