ماڈیول اسباق (3/5)
ساخت (ایمبیڈنگ)
جاؤ کوئی وراثت نہیں ہے۔ دوبارہ استعمال کرنے کا محاورہ جواب ہے۔ کمپوزیشن، اور خاص طور پر ایمبیڈنگ: ایک قسم سمیت فیلڈ کا نام دیئے بغیر دوسرے کے اندر۔ کے میدان اور طریقے سرایت شدہ قسم کو فروغ دیا گیا، براہ راست قابل رسائی بننا گویا وہ بیرونی قسم سے تعلق رکھتے تھے۔
سٹرک ایمبیڈنگ
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 سے مماثل ہے۔ اس کی ضرورت ہے جب
تصادم ہیں.
اوور رائڈ (جزوی): طریقہ "شیڈونگ"
اگر بیرونی قسم اسی نام کے ساتھ ایک طریقہ کی وضاحت کرتی ہے جسے فروغ دیا گیا ہے۔ ایک، اس کا طریقہ "جیت"۔ اندر سے آپ ہمیشہ ایمبیڈڈ تک پہنچ سکتے ہیں۔ ایک قسم کے نام کے ذریعے:
func (c Dog) Greet() string {
return "BAU! " + c.Animal.Greet()
}یہ پولیمورفک وراثت نہیں ہے: یہ صرف لغوی نام کی قرارداد ہے۔ پولیمورفزم کے لیے آپ انٹرفیس (ماڈیول 6) استعمال کرتے ہیں۔
ایک سے زیادہ سرایت کرنا
آپ متعدد اقسام کو سرایت کر سکتے ہیں:
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 دیکھیں):
type ReadWriter interface {
io.Reader
io.Writer
}یہ Reader اور Writer کے طریقوں کے اتحاد کے برابر ہے۔
واضح کمپوزیشن کب استعمال کریں (ایمبیڈنگ نہیں)
اگر آپ ایک نامزد فیلڈ چاہتے ہیں اور کوئی آٹو پروموشن نہیں ہے تو سادہ استعمال کریں۔ ترکیب:
type Dog struct {
Anim Animal // NORMAL field, no promotion
Breed string
}
c.Anim.Name // you need the field nameسرایت کرنا ایک آسان ڈیلی گیشن ٹول ہے، ڈیزائن کا انتخاب نہیں۔ واضح مرکب سے سختی سے بہتر: جب آپ واقعی چاہیں استعمال کریں۔ اندرونی قسم کے API کو فروغ دینے کے لیے۔
اسے آزمائیں
کتے کی وضاحت کریں جو جانوروں کو سرایت کرتا ہے (ایمبیڈنگ، فیلڈ کا کوئی نام نہیں) اور اس کے پاس بریڈ سٹرنگ فیلڈ ہے۔
اشارہ دکھائیں۔
ایمبیڈنگ: TYPE کو فیلڈ کا نام دیئے بغیر لکھیں۔
3 کوششوں کے بعد حل دستیاب ہے۔
Animal میں Greet() سٹرنگ کا طریقہ شامل کریں اور اسے براہ راست ڈاگ متغیر (طریقہ فروغ) پر کال کریں۔
اشارہ دکھائیں۔
اینیمل پر بیان کردہ طریقہ کو سرایت کرنے کی بدولت کتے میں فروغ دیا جاتا ہے۔
3 کوششوں کے بعد حل دستیاب ہے۔
کیا گو کلاسیکی وراثت کی حمایت کرتا ہے؟
type B struct { /* extends A? */ }Recap
- کوئی وراثت نہیں: آپ ایمبیڈنگ کے ساتھ کمپوز کرتے ہیں۔
- ایمبیڈنگ = ساخت میں فیلڈ کے نام کے بغیر ٹائپ لکھنا۔
- سرایت شدہ قسم کے فیلڈز اور طریقوں کو فروغ دیا جاتا ہے۔
- واضح رسائی ہمیشہ دستیاب ہے:
outer.Inner.Field۔ - "لغوی" اوور رائڈ: بیرونی قسم کا طریقہ ترقی یافتہ کو سایہ کرتا ہے۔
- ایمبیڈنگ ≠ is-a: پولیمورفزم کے لیے انٹرفیس استعمال کریں۔