2011-02-15 19 views
118

में बिल्डर पैटर्न मैंने हाल ही में जोशुआ ब्लोच द्वारा प्रभावी जावा को पढ़ना शुरू कर दिया है। मुझे बिल्डर पैटर्न [पुस्तक में आइटम 2] का विचार वास्तव में दिलचस्प लगता है। मैंने इसे अपने प्रोजेक्ट में लागू करने की कोशिश की लेकिन संकलन त्रुटियां थीं। बाद सार में है कि मैं क्या करने की कोशिश कर रहा था:प्रभावी जावा

कई विशेषताओं के साथ वर्ग और उसके बिल्डर वर्ग:

public class Main { 
    public static void main(String args[]) { 
     NutritionalFacts n = 
      new NutritionalFacts.Builder(10).carbo(23).fat(1).build(); 
    } 
} 

मैं:

public class NutritionalFacts { 
    private int sodium; 
    private int fat; 
    private int carbo; 

    public class Builder { 
     private int sodium; 
     private int fat; 
     private int carbo; 

     public Builder(int s) { 
      this.sodium = s; 
     } 

     public Builder fat(int f) { 
      this.fat = f; 
      return this; 
     } 

     public Builder carbo(int c) { 
      this.carbo = c; 
      return this; 
     } 

     public NutritionalFacts build() { 
      return new NutritionalFacts(this); 
     } 
    } 

    private NutritionalFacts(Builder b) { 
     this.sodium = b.sodium; 
     this.fat = b.fat; 
     this.carbo = b.carbo; 
    } 
} 

कक्षा जहां मैं ऊपर वर्ग इस्तेमाल करने की कोशिश निम्नलिखित संकलक त्रुटि प्राप्त कर रहा हूं:

an enclosing instance that contains effectivejava.BuilderPattern.NutritionalFacts.Builder is required NutritionalFacts n = new NutritionalFacts.Builder(10).carbo(23).fat(1).build();

मुझे समझ में नहीं आता कि संदेश का क्या अर्थ है। कृपया समझाएँ। उपरोक्त कोड ब्लोच द्वारा अपनी पुस्तक में सुझाए गए उदाहरण के समान है।

+1

संभव डुप्लिकेट [एक enclosing उदाहरण जिसमें <मेरे संदर्भ> की आवश्यकता है] (http://stackoverflow.com/questions/ 4297857/एक-संलग्न-उदाहरण-जिसमें-मेरा-संदर्भ-आवश्यक है) –

उत्तर

145

बिल्डर को static कक्षा बनाएं। फिर यह काम करेगा। यदि यह गैर स्थैतिक है, तो उसे अपनी खुद की कक्षा के उदाहरण की आवश्यकता होगी - और बिंदु का इसका उदाहरण नहीं होना चाहिए, और यहां तक ​​कि निर्माता के बिना उदाहरण बनाने से मना करना भी है।

public class NutritionFacts { 
    public static class Builder { 
    } 
} 

संदर्भ: Nested classes

+25

और, वास्तव में, पुस्तक में उदाहरण में 'बिल्डर' 'स्थिर 'है (पृष्ठ 14, द्वितीय संस्करण में पंक्ति 10)। – Powerlord

4

इसका मतलब यह है कि आप संलग्न प्रकार नहीं बना सकते हैं। इसका मतलब है कि सबसे पहले आपको "पैरेंट" वर्ग का उदाहरण देना होगा और फिर इस उदाहरण से आप नेस्टेड क्लास इंस्टेंस बना सकते हैं।

NutritionalFacts n = new NutritionalFacts() 

Builder b = new n.Builder(10).carbo(23).fat(1).build(); 

Nested Classes

+3

जो अधिक समझ में नहीं आता है, क्योंकि उसे "तथ्यों" का निर्माण करने के लिए निर्माता की आवश्यकता होती है, न कि दूसरी तरफ। – Bozho

+4

सत्य अगर हम बिल्डर पैटर्न पर ध्यान केंद्रित करते हैं, तो मैंने केवल "मुझे समझ में नहीं आता कि संदेश का क्या अर्थ है" पर ध्यान केंद्रित किया, और दो समाधानों में से एक प्रस्तुत किया। –

7

आप static रूप Builder भीतरी वर्ग घोषित करने के लिए की जरूरत है।

non-static inner classes और static inner classes दोनों के लिए कुछ दस्तावेज़ों से परामर्श लें।

असल में गैर स्थैतिक आंतरिक कक्षा के उदाहरण संलग्न बाहरी वर्ग उदाहरण के बिना मौजूद नहीं हो सकते हैं।

4

बिल्डर वर्ग स्थिर होना चाहिए। मेरे पास वास्तव में उस से परे कोड का परीक्षण करने के लिए अभी समय नहीं है, लेकिन अगर यह काम नहीं करता है तो मुझे बताएं और मैं एक और नजर डालेगा।

11

आप एक स्थिर तरीके से उपयोग एक गैर स्थैतिक कक्षा कोशिश कर रहे हैं। Builder से static class Builder बदलें और इसे काम करना चाहिए।

आपके द्वारा प्रदान किया जाने वाला उदाहरण उपयोग विफल रहता है क्योंकि Builder मौजूद कोई उदाहरण नहीं है। सभी व्यावहारिक उद्देश्यों के लिए एक स्थिर वर्ग हमेशा तत्काल होता है। क्योंकि आप एक नया Builder हर बार का निर्माण करने की आवश्यकता होगी

Widget = new Widget.Builder(10).setparm1(1).setparm2(3).build(); 

: आप इसे स्थिर नहीं बनाते हैं, तो आप कहने की जरूरत होगी।

10

IntelliJ विचार में एक आंतरिक बिल्डर उत्पन्न करने के लिए इस प्लगइन की जाँच: https://github.com/analytically/innerbuilder

+2

इस सवाल के साथ कुछ भी नहीं है लेकिन बहुत उपयोगी है! अच्छा लगता है! –

22

आप बिल्डर वर्ग के रूप में स्थिर करना चाहिए और यह भी आप क्षेत्रों अंतिम बनाने के लिए और उन मूल्यों को प्राप्त करने के लिए ही टिककर खेल नहीं होनी चाहिए। उन मूल्यों पर सेटर्स प्रदान न करें। इस तरह आपकी कक्षा पूरी तरह से अपरिवर्तनीय होगी।

public class NutritionalFacts { 
    private final int sodium; 
    private final int fat; 
    private final int carbo; 

    public int getSodium(){ 
     return sodium; 
    } 

    public int getfat(){ 
     return fat; 
    } 

    public int getCarbo(){ 
     return carbo; 
    } 

    public static class Builder { 
     private int sodium; 
     private int fat; 
     private int carbo; 

     public Builder sodium(int s) { 
      this.sodium = s; 
      return this; 
     } 

     public Builder fat(int f) { 
      this.fat = f; 
      return this; 
     } 

     public Builder carbo(int c) { 
      this.carbo = c; 
      return this; 
     } 

     public NutritionalFacts build() { 
      return new NutritionalFacts(this); 
     } 
    } 

    private NutritionalFacts(Builder b) { 
     this.sodium = b.sodium; 
     this.fat = b.fat; 
     this.carbo = b.carbo; 
    } 
} 

और अब आप इस प्रकार के गुण निर्धारित कर सकते हैं:

NutritionalFacts n = new NutritionalFacts.Builder().sodium(10).carbo(15). 
fat(5).build(); 
की
+0

क्यों न केवल खेतों को सार्वजनिक बनाते हैं? वे पहले से ही अंतिम हैं, और यह अभी भी अपरिवर्तनीय होगा। –