2011-11-07 15 views
6

विरासत में यह एक बुरा समस्या है, और यह हो सकता है कि डिज़ाइन बस खराब हो।कुछ खराब जावा जेनेरिक

सरल चार्ट घटकों (पाई, बार & लाइन चार्ट) का एक सेट लिखना और कुछ जेनेरिक सामानों पर चकमा दे रहा हूं। अग्रिम में, मुझे यकीन है कि मैं ऐसा करने के लिए कई जावा एपीआई कर रहा हूं जो मैं यहां करने की कोशिश कर रहा हूं (चार्टिंग/रिपोर्ट/आदि), हालांकि मुझे सामान्य जेनेरिक समस्या के रूप में इसमें रूचि है; तथ्य यह है कि इसमें चार्ट & रिपोर्टिंग घटक शामिल हैं।

हर चार्ट एक सामान्य सार आधार वर्ग Chart से विरासत:

public abstract class Chart<T extends ChartComponent> 
{ 
    private List<T> components; 

    // ...rest of the Chart class 
} 

कारण है कि हम T extends ChartComponent है हर चार्ट उपवर्ग 1+ तथाकथित चार्ट घटकों (बार, लाइनों के शामिल हो जाएगा, क्योंकि क्यों है , पाई wedges, आदि):

public abstract class ChartComponent 
{ 
    private Color color; 

    // .. rest of ChartComponent class 
} 

public class PieWedge extends ChartComponent 
{ 
    double wedgeValue; 

    // ... rest of PieWedge class 
} 

एक साथ इस डिजाइन लाना:

public class PieChart extends Chart<PieWedge> 
{ 
    // ... thus its list of ChartComponents is actually a List<PieWedge> 
} 

इस तरह, PieChart साधारण नहीं है (और न ही यह होना चाहिए) और प्रकार Chart<PieWedge> की हमेशा होता है।

मेरे पास पहले बार और लाइन चार्ट के लिए एक ही सेटअप था, जिसे BarChart extends Chart<BarGroup> और LineChart extends Chart<Line> के रूप में परिभाषित किया गया था (चूंकि एक बार चार्ट में बार के 1+ समूह होते हैं, और एक रेखा चार्ट में 1+ रेखाएं होती हैं)।

अब मैं बार और लाइन चार्ट को और भी आगे करना चाहता हूं। इन दोनों चार्टों को वास्तव में एक्स (और वाई-अक्ष के साथ एक (एक्स, वाई) कार्टेशियन ग्राफ के खिलाफ प्लॉट किया गया है; यह एक पाई चार्ट के विपरीत है जो किसी भी अक्ष के खिलाफ प्लॉट नहीं किया गया है।

आदर्श रूप में, मैं CartesianChart जो Chart बढ़ाया नामक एक नई अमूर्त वर्ग बनाने के लिए, और फिर BarChart और LineChart दोनों का विस्तार CartesianChart चाहता था। यह नया CartesianChart नई गुणों (xAxisLabel, gridTurnedOn इत्यादि) पेश करेगा जो तार्किक रूप से बार/रेखा चार्ट पर लागू होते हैं लेकिन पाई चार्ट नहीं।

इसके अलावा, CartesianChart प्रतिबंधित करने के लिए इतना है कि यह केवल प्रकार BarGroup या Line (और नहीं PieWedge) की chartComponents हो सकता था, मैं CartesianComponent extends ChartComponent की तरह एक नया चार्ट घटक प्रकार बनाने के लिए चाहते हैं, और फिर BarGroup/Line कि विस्तार की है। ऐसा करने से संकलन से इस तरह कोड रोका जा सके:

LineChart lineChart = new LineChart(); 
lineChart.addLine(new PieWedge()); 

Line के बाद से CartesianComponent फैली हुई है, लेकिन PieWedge केवल ChartComponent फैली हुई है।

Chart 
    CartesianChart 
     BarChart 
     LineChart 
    PieChart 

ChartComponent 
    CartesianComponent 
     BarGroup 
     Line 
    PieWedge 

PieChart extends Chart<PieWedge> 

CartesianChart extends Chart<CartesianComponent> 

BarGroup extends CartesianComponent 
Line extends CartesianComponent 

BarChart extends CartesianChart<BarGroup> 
LineChart extends CartesianChart<Line> 

इस सेटअप के साथ समस्या यह है कि BarChart और LineChart दोनों पर यह शिकायत की कि CartesianChart साधारण नहीं है एक संकलक त्रुटि देता है: इस प्रकार, मेरी समस्या के लिए हो रही इससे पहले कि हम निम्नलिखित वंशानुगत पदानुक्रम की है। यह पूरी तरह से समझ में आता है, लेकिन मुझे यकीन नहीं है कि मैं इसे ठीक करने के लिए क्या कर सकता हूं!

अगर मैं करने की कोशिश फिर से परिभाषित CartesianChart:

public abstract class CartesianChart<T extends CartesianComponent> extends Chart<CartesianComponent> 
{ 
    // ... 
} 

मैं सभी मेरे बार/लाइन चार्ट कोड के माध्यम से "प्रकार बेमेल 'संकलक त्रुटियों मिलता है। त्रुटि के हर उदाहरण में, यह बताता है कि यह List<CartesianComponent> के तर्कों की अपेक्षा कर रहा है लेकिन इसके बजाय List<BarGroup> या List<Line> पाया गया है और वे उपयुक्त विकल्प नहीं हैं।

उम्मीद है, इस CartesianChart और/या CartesianComponent के वर्ग परिभाषा त्वरित सुधार कहीं है। अन्यथा मुझे पूरे चार्ट लाइब्रेरी को फिर से डिज़ाइन करना पड़ सकता है। किसी भी तरह से, मुझे किसी भी और सभी सुझावों में दिलचस्पी है, को छोड़कर "अरे, आप केवल JFreeCharts या ..." क्यों नहीं आते हैं। दोबारा, मुझे यहां समाधान में दिलचस्पी है क्योंकि यह समान जेनेरिक समस्याओं की एक विस्तृत श्रृंखला को हल करने से संबंधित है; तथ्य यह है कि इसमें रिपोर्टिंग/चार्टिंग शामिल है तुच्छ है।

किसी भी और सभी मदद के लिए अग्रिम धन्यवाद!

+0

'चार्ट' जेनेरिक बनाकर आप क्या हासिल करने की कोशिश कर रहे हैं? दूसरे शब्दों में, क्यों न केवल 'चार्ट चार्ट {निजी सूची <चार्टकंपोनेंट> घटक परिभाषित करें; } '? –

+0

'सार्वजनिक सार श्रेणी कार्टेशियन चार्ट <टी कार्टेशियन कॉम्पोनेंट बढ़ाता है> चार्ट ' बढ़ाता है? – digitaljoel

+0

यहां सुझावों के लिए धन्यवाद। मैं यहां आपके दोनों सुझावों का प्रयास करूंगा। कृपया मेरे डर के बारे में @ nicholas.hauschild के उत्तर के नीचे मेरी टिप्पणी देखें कि चार्ट विस्तारित करने से उप-वर्गों को चार्ट बनाने की रोकथाम नहीं होगी जहां टी चार्टकंपोनेंट का विस्तार नहीं करता है। – IAmYourFaja

उत्तर

4

आपका Chart वर्ग List<T> है कि आप की बात शामिल है, इसलिए जब आप आप Chart<CartesianComponent> विस्तार करने के लिए अपने CartesianChart सार वर्ग को परिभाषित, आप कह रहे हैं कि वास्तव में List<T>List<CartesianComponent> है।

वास्तव में, आप जो चाहते हैं वह जेनेरिक का उपयोग करना है क्योंकि आपने इसे अपनी अमूर्त कक्षा (यानी, <T extends CartesianComponent>) में परिभाषित किया है। मैं ऐसा करने की कोशिश करता हूं और देखता हूं कि यह कैसे काम करता है।

public abstract class CartesianChart<T extends CartesianComponent> extends Chart<T> 
{ 
    // ... 
} 
+0

यह एक बहुत अच्छा सुझाव है (और धन्यवाद!), हालांकि मुझे चिंता है कि इससे सबक्लास को इस तरह परिभाषित किया जाएगा: पब्लिक क्लास आरेख चार्ट बढ़ाता है, जहां विजेट चार्टकंपोनेंट सबक्लास नहीं है। यह महत्वपूर्ण है कि चार्टकंपोनेंट से सभी प्रकार के "टी" के उत्तराधिकारी (कुछ बिंदु पर)। – IAmYourFaja

+0

यह वास्तव में नहीं होगा, क्योंकि आपने इस स्कोप में 'टी' को पहले से ही 'कार्टेशियन कॉम्पोनेंट' तक सीमित किया है (प्रति 'कार्टेशियन चार्ट <टी कार्टेशियन कॉम्पोनेंट>' बढ़ाता है)। मेरे सुझाव का प्रयास करें और फिर इसे 'विजेट' जोड़ने का प्रयास करें ... –

+0

बहुत बढ़िया, भयानक, भयानक। फिर से धन्यवाद! – IAmYourFaja

0

इंटरफेस का उपयोग करें।

public interface IsAPieChart { 

} 

public interface IsACartesianChart { 

} 

उन्हें किसी भी तरीके की आवश्यकता नहीं है।

addLine के लिए आपका विधि प्रोफाइल() लिखा होगा:

public void addLine(IsACartesianChart cartesianChart); 

आपका सार वर्गों में लिखा होगा:

public class PieChart extends Chart<PieWedge> implements IsAPieChart 
{ 
    // ... thus its list of ChartComponents is actually a List<PieWedge> 
} 

और उसी तरह से CartesianChart चिह्नित करने के लिए IsACartesianChart का उपयोग करें। अब addLine() PieChart के कुछ भी स्वीकार नहीं करेगा क्योंकि कोई पाइचार्ट ISACartesianChart इंटरफ़ेस लागू नहीं करता है, लेकिन यह CartesianChart के उप-वर्ग के कुछ भी ले जाएगा क्योंकि सभी उप-वर्ग ISACartesianChart को लागू करते हैं।

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

0

कारण है कि हम T extends ChartComponent है हर चार्ट उपवर्ग 1+ तथाकथित चार्ट घटकों (बार, लाइन, पाइ wedges, आदि) के शामिल हो जाएगा, क्योंकि क्यों है:

यह वह जगह है आपका लाल हेरिंग, यहां जेनेरिक का उपयोग करने की आवश्यकता नहीं है। यह Composition समस्या है, Generics समस्या नहीं है।

बस अपनी सूची देखो की तरह:

private List<ChartComponent> components; 

यह सभी प्रकार के सुरक्षा की जरूरत है चाहिए।

+0

धन्यवाद! जब मुझे मौका मिलेगा तो मैं इस सप्ताह के अंत में इस सुझाव का प्रयास करूंगा। – IAmYourFaja

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