मुख्य सामग्री पर जाएं
मॉड्यूल 5 · पाठ 3 का 5पाठ्यक्रम में 23/50~12 min
मॉड्यूल पाठ (3/5)

रचना (एम्बेडिंग)

गो की कोई विरासत नहीं है। पुन: उपयोग का मुहावरेदार उत्तर है रचना, और विशेष रूप से एम्बेडिंग: एक प्रकार सहित फ़ील्ड नाम दिए बिना दूसरे के अंदर। के क्षेत्र और तरीके एम्बेडेड प्रकार को पदोन्नत किया जाता है, मानो वह सीधे पहुंच योग्य हो जाता है वे बाहरी प्रकार के थे।

संरचना एम्बेडिंग

Go
type Animal struct {
    Name string
}

func (a Animal) Greet() string {
    return "ciao da " + a.Name
}

type Dog struct {
    Animal        // embedding — NO field name
    Breed string
}

c := Dog{
    Animal: Animal{Name: "Rex"},
    Breed:  "Pastore",
}

fmt.Println(c.Name)         // "Rex" — promoted from Animal
fmt.Println(c.Greet())      // "ciao da Rex" — promoted method
fmt.Println(c.Breed)        // own field

एम्बेडेड फ़ील्ड अभी भी प्रकार के नाम से पहुंच योग्य है: c.Animal.Name काम करता है और c.Name के समान है। इसकी जरूरत तब पड़ती है टकराव होते हैं.

ओवरराइड (आंशिक): विधि "छायाांकन"

यदि बाहरी प्रकार प्रचारित के समान नाम के साथ एक विधि को परिभाषित करता है एक, इसकी विधि "जीतती है"। अंदर से आप हमेशा अंतर्निहित तक पहुंच सकते हैं प्रकार के नाम के माध्यम से एक:

Go
func (c Dog) Greet() string {
    return "BAU! " + c.Animal.Greet()
}

यह बहुरूपी वंशानुक्रम नहीं है: यह केवल शाब्दिक नाम संकल्प है। बहुरूपता के लिए आप इंटरफ़ेस (मॉड्यूल 6) का उपयोग करते हैं।

एकाधिक एम्बेडिंग

आप कई प्रकार एम्बेड कर सकते हैं:

Go
type Logger struct{ /*...*/ }
func (l Logger) Log(msg string) { /*...*/ }

type Timer struct{ /*...*/ }
func (t Timer) Now() time.Time { /*...*/ }

type Service struct {
    Logger
    Timer
    Name string
}

s := Service{Name: "api"}
s.Log("start")   // promoted from Logger
s.Now()          // promoted from Timer

यदि दो एम्बेडेड प्रकारों में एक ही नाम वाली एक विधि है, तो सीधी पहुंच अस्पष्ट हो जाता है और संकलक को स्पष्ट रूप की आवश्यकता होती है (s.Logger.Foo() या s.Timer.Foo())।

इंटरफ़ेस एम्बेडिंग

इंटरफ़ेस को "एम्बेडेड" भी किया जा सकता है (मॉड्यूल 6 देखें):

Go
type ReadWriter interface {
    io.Reader
    io.Writer
}

यह Reader और Writer के तरीकों के मिलन के बराबर है।

स्पष्ट रचना का उपयोग कब करें (एम्बेडिंग नहीं)

यदि आप एक नामित फ़ील्ड चाहते हैं और कोई ऑटो-प्रमोशन नहीं है, तो सादे का उपयोग करें रचना:

Go
type Dog struct {
    Anim  Animal    // NORMAL field, no promotion
    Breed string
}
c.Anim.Name   // you need the field name

एंबेडिंग एक आसान प्रतिनिधि उपकरण है, डिज़ाइन विकल्प नहीं स्पष्ट रूप से स्पष्ट रचना से बेहतर: जब आप वास्तव में चाहें तब इसका उपयोग करें आंतरिक प्रकार के एपीआई को बढ़ावा देने के लिए।

इसे अजमाएं

व्यायाम#go.m5.l3.e1
प्रयास: 0लोड हो रहा है...

कुत्ते को परिभाषित करें जो एनिमल को एम्बेड करता है (एम्बेडिंग, कोई फ़ील्ड नाम नहीं) और एक ब्रीड स्ट्रिंग फ़ील्ड है।

संपादक लोड हो रहा है...
संकेत दिखाएँ

एम्बेडिंग: TYPE को फ़ील्ड का नाम दिए बिना लिखें।

3 प्रयासों के बाद समाधान उपलब्ध है

व्यायाम#go.m5.l3.e2
प्रयास: 0लोड हो रहा है...

एनिमल में एक ग्रीट() स्ट्रिंग विधि जोड़ें और इसे सीधे डॉग वेरिएबल (विधि प्रचार) पर कॉल करें।

संपादक लोड हो रहा है...
संकेत दिखाएँ

एम्बेडिंग की बदौलत एनिमल पर परिभाषित विधि को डॉग में प्रचारित किया गया है।

3 प्रयासों के बाद समाधान उपलब्ध है

Quiz#go.m5.l3.e3
तैयार

क्या गो शास्त्रीय विरासत का समर्थन करता है?

Go
type B struct { /* extends A? */ }
उत्तर विकल्प

संक्षिप्त

  • कोई विरासत नहीं: आप एम्बेडिंग के साथ रचना करते हैं।
  • एंबेडिंग = संरचना में फ़ील्ड नाम के बिना प्रकार लिखना।
  • एम्बेडेड प्रकार के फ़ील्ड और तरीकों को पदोन्नत किया जाता है।
  • स्पष्ट पहुंच हमेशा उपलब्ध है: outer.Inner.Field।
  • "लेक्सिकल" ओवरराइड: बाहरी प्रकार की विधि प्रचारित विधि को छाया देती है।
  • एम्बेडिंग ≠ है-एक: बहुरूपता के लिए इंटरफ़ेस का उपयोग करें।