2012-11-08 26 views
12

में अंतिम कक्षा का विस्तार कैसे करें मेरी समस्या वास्तव में अब मुझे सामना कर रही है। मेरे पास कक्षा है, मान लें Foo और यह वर्ग getBar नामक एक विधि को परिभाषित करता है जो Bar उदाहरण देता है। कक्षा Bar को Foo के अंदर परिभाषित किया गया है और इसे public static final घोषित किया गया है। मैं क्या करना चाहता हूं MyFoo जो Foo बढ़ाता है, लेकिन मैं BarMyBar के साथ अपनी खुद की कार्यक्षमताओं (विधियों, गुणों, आदि) को जोड़कर विस्तार करना चाहता हूं। मैं भी MyBar लौटने के लिए चाहता हूं।जावा

समस्या Bar अंतिम है।

public class Foo { 

    Bar bar = new Bar(); 

    public Bar getBar(){ 
     return bar; 
    } 

    .... 

    public static final class Bar { 

    } 
} 

मुझे क्या करना चाहते हैं::

public class MyFoo extends Foo { 


    public MyBar getBar(){ // here I want to return an instance of MyBar 

    } 

    public static final class MyBar extends Bar { // That's impossible since Bar is final 

    } 
} 

मैं ऐसा कैसे प्राप्त कर सकते हैं यहाँ मैं क्या करना चाहते हैं का एक उदाहरण है?

[संपादित करें] मैं अपने प्रश्न में अधिक जानकारी जोड़ रहा हूं। मैं वास्तव में जेनकींस के लिए एक प्लगइन विकसित कर रहा हूं और खोज के बाद, मुझे एहसास है कि एक प्लगइन है जो बेस कार्यक्षमताओं को प्रदान करता है जो मैं करना चाहता हूं, Foo और Bar। मैं Foo और Bar कस्टम करना चाहता हूं, इसलिए यह मेरी आवश्यकताओं को फिट कर सकता है। फू प्लगइन का मुख्य वर्ग है और बिल्डर नामक कक्षा को बढ़ाता है। फू perform नामक एक विधि को परिभाषित करता है जिसमें निर्माण करने के लिए सभी संचालन शामिल हैं। Bar में कॉन्फ़िगरेशन उद्देश्यों के लिए संचालन शामिल हैं और Foo को उन सूचनाओं को प्राप्त करने के लिए बार की आवश्यकता है।

तो मैं MyFoo के साथ Foo का विस्तार करना चाहता हूं और MyBar के साथ कुछ कॉन्फ़िगरेशन जोड़ना चाहता हूं। और जैसा कि आप देख सकते हैं, MyFoogetBar();

बुला दूसरी बात करके उन configuations पाने के लिए की आवश्यकता होगी मैं MyFoo की instanciation का कोई नियंत्रण नहीं है और MyBar

क्या मुझे ब्लॉक है, यह है कि मैं बार विस्तार नहीं कर सकते है। मैं उसे कैसे प्राप्त कर सकता हूं?

+8

चूंकि 'अंतिम' संशोधक आपको 'बार' उप-वर्ग से रोकता है, इसलिए मैं इसे "रैपिंग" करने की अनुशंसा करता हूं। – mre

+0

यदि 'बार' एक 'अंतिम श्रेणी' है तो यह आमतौर पर कुछ अच्छे कारणों के लिए होता है, उदा। अत्याचार क्योंकि 'फू' के कुछ आविष्कारों की आवश्यकता है। तो मैं ऐसा नहीं करूँगा, या कम से कम आपको सभी प्रासंगिक स्रोत कोड को समझना चाहिए, और शायद इसे फिर से लिखना चाहिए। –

+2

इसे 'गैर' के डेवलपर से नॉन-फाइनल बनाने के लिए पूछें या प्रतिनिधिमंडल का उपयोग करें, जैसा कि सुझाव देता है। –

उत्तर

26

आप मूल रूप से नहीं कर सकते हैं। यह डेवलपर की तरह दिखता है जिसने Bar डिज़ाइन किया है जिसका उद्देश्य विस्तारित नहीं किया जाना चाहिए - ताकि आप इसे विस्तारित नहीं कर सकें। आपको एक अलग डिज़ाइन की तलाश करनी होगी - संभवतः वह जो विरासत का इतना उपयोग नहीं करता है ... मान लीजिए कि आप मौजूदा कोड को बिल्कुल नहीं बदल सकते हैं।

(यहां यह वास्तविक लक्ष्य के बारे में अधिक जानने के बिना अधिक ठोस सलाह देने के लिए मुश्किल है -। समग्र प्रणाली के डिजाइन)

+1

ठीक है, मैं वास्तव में जेनकींस के लिए एक प्लगइन विकसित कर रहा हूं और यह बात है कि फू और बार में बहुत सारी कार्यक्षमताएं हैं जिन्हें मैं विस्तारित करना चाहता हूं। इससे मुझे फू और बार – Dimitri

+1

@ डिमिट्री के समान कोड को फिर से लिखने से रोका जा सकता है: यह वास्तव में हमें यह जानने के लिए पर्याप्त जानकारी नहीं देता है कि उदाहरण के लिए विरासत की बजाय संरचना का उपयोग करना उचित होगा या नहीं। –

+0

'फू' और 'बार' जानबूझकर डिजाइन किए गए थे ताकि आप उन्हें विस्तारित न कर सकें। आपके पास वास्तव में कोई विकल्प नहीं है। –

4

आप अंतिम कक्षाओं का विस्तार नहीं कर सकते हैं, कि अंतिम वर्गों की घोषणा की है। आप एक इंटरफ़ेस को परिभाषित कर सकते हैं कि अंतिम श्रेणी से उत्तराधिकारी और एक रैपर वर्ग जो लिपटे अंतिम श्रेणी में कॉल करता है। प्रश्न यह है कि क्लास फाइनल को पहले स्थान पर क्यों बनाना है।

6

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

बेशक इस final वर्ग की निजी & संरक्षित क्षेत्रों के लिए उपयोग नहीं देंगे, लेकिन आप अपने getters और setters तरीकों, नए तरीकों के साथ संयुक्त का उपयोग कर सकते & क्षेत्रों आप Wrapper वर्ग में घोषित परिणाम आप प्राप्त करने के लिए चाहते हैं, या कुछ अपेक्षाकृत करीब है।

एक और समाधान final एक वर्ग घोषित नहीं करना है यदि ऐसा करने के लिए कोई वैध कारण नहीं है।

5

आप final कक्षा का विस्तार नहीं कर सकते - यह final कीवर्ड का उद्देश्य है।

हालांकि, देखते हैं (कम से कम) दो काम arounds:

  1. वर्ग, जेनकींस परियोजना है, जो खुला स्रोत है में है, इसलिए आप बस परियोजना डाउनलोड, परिवर्तन करने के लिए आप चाहते हैं कर सकते हैं वर्ग और जार
  2. हैक की कुछ हद तक
  3. फिर से निर्माण, लेकिन आप Javassist की तरह एक पुस्तकालय इस्तेमाल कर सकते हैं स्मृति
+0

कोई क्लास फाइनल क्यों बनायेगा? यह एक भयानक सवाल की तरह लग सकता है लेकिन मैं प्रोग्रामिंग के लिए नया हूँ। मैं स्कैनर वर्ग का विस्तार करने की कोशिश कर रहा था (बस यह देखने के लिए कि मैं कर सकता था) और मैंने देखा कि यह काम नहीं करेगा।मेरे दोस्त ने मुझे बताया कि ऐसा इसलिए था क्योंकि स्कैनर वर्ग अंतिम था। मान लें कि सैद्धांतिक रूप से यह अंतिम नहीं था और किसी ने इसे विस्तारित किया था। क्या समस्या होगी क्योंकि बाल वर्ग के भीतर किसी भी चर को बदल दिया गया है, उसे मूल वर्ग को बदलना नहीं है? इत्यादि। आईडीके –

+0

मुझे पता है कि स्कैनर वर्ग को ओवरराइड होने के साथ इसका कुछ संबंध है, लेकिन अगर मैं अंतिम नहीं था और मैंने कोशिश की तो मुझे इसे ओवरराइट करने का तरीका भी नहीं पता था। –

2

शायद क्या आप चाहते हैं एक प्रॉक्सी है में वर्ग के कार्यान्वयन को बदलने के लिए। इसे कार्यान्वित करना आसान है। http://java.dzone.com/articles/power-proxies-java

0

उदाहरण के लिए हम नहीं एक StringBuffer TreeSet संग्रह में जोड़ सकते हैं, क्योंकि TreeSet तुलनीय इंटरफ़ेस का बच्चा नहीं है::

public class Main(){ 
public static void main(String[] args){ 
    TreeSet treeSetSB = new TreeSet(); 
    treeSetSB.add(new StringBuffer("A")); //error, Comparable is not implemented 
} 

लेकिन हम लागू करने के लिए एक आवरण का उपयोग कर सकते यह एक शानदार लेख है तुलनीय:

class myWrap implements Comparable{ 
    TreeSet treeset; 
    public myWrap() { 
     this.treeset=new TreeSet<>(); 

    } 
    public TreeSet getTreeset() { 
     return treeset; 
    } 
    public void setTreeset(TreeSet treeset) { 
     this.treeset = treeset; 
    } 
} 


public class Main(){ 
public static void main(String[] args){ 

    myWrap myWrap =new myWrap(); 
    TreeSet myTrs =myWrap.getTreeset(); 
    myTrs.add("b"); // no error anymore 
    myTrs.add("a"); 
    myTrs.add("A"); 
    System.out.println(myTrs); 
} 
0

यह कुछ इंटरफेस को लागू करता है, तो Decorator Design pattern समस्या का समाधान कर सकता है।