2015-08-24 10 views
13

मैं अपनी लाइब्रेरी में विधियों के साथ आधार संरचना प्रदान करना चाहता हूं जिसे 'विस्तारित' किया जा सकता है।गोलांग और विरासत

इस आधार संरचना के तरीके विस्तारित संरचना से विधियों पर भरोसा करते हैं। यह गो में सीधे संभव नहीं है, क्योंकि स्ट्रक्चर विधियों के पास केवल मूलभूत structs के लिए structs के अपने क्षेत्र में acces है।

बिंदु यह कार्यक्षमता है कि मुझे प्रत्येक विस्तारित कक्षा में दोहराना नहीं है।

मैं इस पैटर्न के साथ आया हूं, जो ठीक काम करता है, लेकिन इसकी चक्रीय संरचना के कारण काफी दृढ़ दिखता है।

मुझे अन्य गो कोड में ऐसा कुछ भी नहीं मिला है। क्या यह बहुत ही अनजान है? मैं क्या अलग दृष्टिकोण ले सकता हूं?

type MyInterface interface { 
    SomeMethod(string) 
    OtherMethod(string) 
} 

type Base struct{ 
    B MyInterface 
} 

func (b *Base) SomeMethod(x string) { 
    b.B.OtherMethod(x) 
} 

type Extender struct { 
    Base 
} 

func (b *Extender) OtherMethod(x string) { 
    // Do something... 
} 

func NewExtender() *Extender { 
    e := Extender{} 
    e.Base.B = &e 
    return &e 
} 
+14

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

+11

अपने समाधान को दोबारा डिजाइन करें। जाओ कोई विरासत नहीं है। जो गो सबसे अधिक संभावना प्रदान करता है उसके साथ विरासत को फिर से हटाने की कोशिश कर रहा है। – Volker

+10

समझ में नहीं आता कि आप क्यों नीचे जा रहे हैं; आपने पूछा कि क्या यह एक उचित दृष्टिकोण था, और यदि नहीं, तो आप इसे बेहतर बनाने के लिए क्या कर सकते हैं। अजीब लड़के की तरह दिखने के जोखिम पर, मुझे लगता है कि आपका प्रश्न ठीक है। ऐसा कहा जा रहा है कि, मेरे ऊपर दो टिप्पणीकारों ने इसे जगह पर मारा। –

उत्तर

11

जैसा कि लोगों की टिप्पणियों में उल्लिखित है, जाओ विरासत पर संरचना को प्रोत्साहित करता है।

कोड डुप्लिकेशन को कम करने के बारे में अपने प्रश्न को हल करने के लिए, आप embedding का उपयोग करना चाहेंगे।

type Reader interface { 
    Read(p []byte) (n int, err error) 
} 

type Writer interface { 
    Write(p []byte) (n int, err error) 
} 

तो आप या तो इंटरफेस एक साथ एक और इंटरफेस में रचना कर सकते हैं::

// ReadWriter is the interface that combines the Reader and Writer interfaces. 
type ReadWriter interface { 
    Reader 
    Writer 
} 

Effective Go ऊपर लिंक से उदाहरण का उपयोग करना, आप बहुत ही संकीर्ण इंटरफेस है कि केवल कुछ ही बातें करते हैं के साथ शुरू यह structs के लिए समान रूप से काम करता है, जहां आप अन्य संरचनाओं में रीडर और राइटर को एक साथ लागू करने वाले structs लिख सकते हैं:

type MyReader struct {} 
func (r *MyReader) Read(p []byte) (n int, err error) { 
    // Implements Reader interface. 
} 
type MyWriter struct {} 
func (w *MyWriter) Write(p []byte) (n int, err error) { 
    // Implements Writer interface. 
} 

// MyReadWriter stores pointers to a MyReader and a MyWriter. 
// It implements ReadWriter. 
type MyReadWriter struct { 
    *MyReader 
    *MyWriter 
} 

असल में, Reader या Writer लागू करने वाली कोई भी चीज़ उन्हें एक संरचना में एक साथ लिखकर पुन: उपयोग की जा सकती है, और बाहरी संरचना स्वचालित रूप से ReaderWriter इंटरफ़ेस को कार्यान्वित करेगी।

यह मूल रूप से Dependency Injection कर रहा है, और यह भी परीक्षण के लिए बहुत उपयोगी है। ऊपर struct कोड से

उदाहरण: बताते

func (rw *MyReadWriter) DoCrazyStuff() { 
    data := []byte{} 
    // Do stuff... 
    rw.Read(data) 
    rw.Write(data) 
    // You get the idea... 
} 

func main() { 
    rw := &MyReadWriter{&MyReader{}, &MyWriter{}} 
    rw.DoCrazyStuff() 
} 

एक बात है कि अन्य भाषाओं 'रचना प्रतिमान से थोड़ा अलग है कि MyReadWriter struct अब दोनों एक Reader और एक Writer के रूप में कार्य कर सकते हैं। यही कारण है कि DoCrazyStuff() में हम rw.Reader.Read(data) के बजाय rw.Read(data) करते हैं।

अद्यतन: गलत गलत उदाहरण।

+0

सिवाय इसके कि आप लगभग किसी इंटरफ़ेस में पॉइंटर का उपयोग नहीं करना चाहते हैं। आपके 'MyReadWriter' ** ** ** को इंटरफेस के लिए पॉइंटर्स का उपयोग नहीं करना चाहिए, बल्कि इसके बजाय' MyReadWriter struct {Reader, Writer} टाइप करें। यह (उदा।) 'Rw: = MyReadWriter {strings.NewReader ("foo"), नया (बाइट्स बफर)} 'के लिए अनुमति देता है। –

+0

सिर के लिए धन्यवाद, यह जानना अच्छा है। क्या आपके पास एक लिंक है जो बताता है क्यों? साथ ही, यह उदाहरण सीधे प्रभावी पृष्ठ से है। – Addison

+0

इंटरफेस के बारे में कुछ और जानकारी प्राप्त करने के लिए एक अच्छी जगह है [Russ Cox द्वारा एक ब्लॉग आलेख] (http://research.swtch.com/interfaces)। –

5

आपको निराश करने के लिए खेद है, लेकिन आप गलत सवाल पूछ रहे हैं। जब मैंने गो कोड लिखना शुरू किया तो मुझे भी इसी तरह की समस्या थी।

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

दुर्भाग्यवश, आपका प्रश्न के बारे में कुछ भी नहीं कहता है समस्या जिसे आप हल करने का प्रयास कर रहे हैं। आपने अभी का वर्णन किया है कि आप इसे हल करना चाहते हैं। इसलिए मैं एक सामान्य उत्तर देने के लिए थोड़ा अनिच्छुक हूं, क्योंकि यह मूर्खतापूर्ण गो कोड का नेतृत्व नहीं करेगा। मैं समझता हूं कि क्या आप उस उत्तर से निराश हैं, लेकिन मेरी राय में, यह सबसे मूल्यवान उत्तर है जो आप प्राप्त कर सकते हैं :)