Golang Interface - مقدماتی

اینترفیس به طور کلی یعنی روشی که بشه باهاش رفتار یه ابجکت رو تعریف کرد و ابجکت هم باید تمام اون رفتار ها رو انجام بده. و آبجکت خودش تصمیم میگیره چگونه این رفتار هارو انجام بده. برای مثال, ماشین لباسشویی ۲ تا رفتار شستن و خشک کردن داره. هر مدل ماشین لباسشوئی باید این ۲ رفتار رو انجام بده ولی به روش خودشون.

- برای ساده سازی تمام کد ها داخل یک فایل نوشته شدن
 - go version go1.14.4 darwin/amd64

حالا اولین قسمت کد را با هم بررسی می کنیم:

package main

import (
   &quotfmt&quot
)

//interface definition
type WashingMachine interface {
   Clean() string
   Dry() string
}

type SamsungModel struct {
   model string
}

//SamsungModel implements Clean
func (s SamsungModel) Clean() string {
   return fmt.Sprintf(&quotSamsung model %s is cleaning&quot, s.model)
}

//SamsungModel implements Dry
func (s SamsungModel) Dry() string {
   return fmt.Sprintf(&quotSamsung model %s is drying&quot, s.model)
}

func main() {
   wm := SamsungModel{&quotSM001&quot}
   var v WashingMachine
   v = wm

   fmt.Println(v.Clean())
   fmt.Println(v.Dry())
} 


اولین قسمت کد تعریف اینترفیس `WashingMachine` است. که مشخص میکنه هر مدل ماشین لباسشویی باید ۲ تا کار `Clean` و `Dry` را حتمن انجام بده. حالا صرف نظر از تعریف اینترفیس, میایم مدل `SamsungModel` را تعریف میکنیم. قسمت مهم کد `v = wm` هست که تایید میکنه `SamsungModel`باید از اینترفیس `WashingMachine` تبعیت کنه. خود `SamsungModel` تصمیم میگیرد که متد های `Clean`و `Dry` را چگونه پیاده سازی کنن ولی نوع خروجی هر کدام باید به اینترفیس یکسان باشن. خروجی کد بالا باید همچین چیزی باشه:

Samsung model SM001 is cleaning
Samsung model SM001 is drying



حالا بیایم یه مدل جدید اضافه کنیم:

package main

import (
   &quotfmt&quot
)

//interface definition
type WashingMachine interface {
   Clean() string
   Dry() string
}

type SamsungModel struct {
   model string
}

//SamsungModel implements Clean
func (s SamsungModel) Clean() string {
   return fmt.Sprintf(&quotSamsung model %s is cleaning&quot, s.model)
}

//SamsungModel implements Dry
func (s SamsungModel) Dry() string {
   return fmt.Sprintf(&quotSamsung model %s is drying&quot, s.model)
}

type LGModel struct {
   model string
   year  int
}

//LGModel implements Clean
func (l LGModel) Clean() string {
   return fmt.Sprintf(&quotLG model %s, year %d is cleaning&quot, l.model, l.year)
}

//LGModel implements Dry
func (l LGModel) Dry() string {
   return fmt.Sprintf(&quotLG model %s, year %d is drying&quot, l.model, l.year)
}

func main() {
   wm := SamsungModel{&quotSM001&quot}
   var v WashingMachine
   v = wm

   wm2 := LGModel{&quotLG001&quot, 2020}
   var v2 WashingMachine
   v2 = wm2

   fmt.Println(v.Clean())
   fmt.Println(v.Dry())

   fmt.Println(v2.Clean())
   fmt.Println(v2.Dry())
}

کاری که کردیم دقیقن مثل حالت اول هست با این تغییر که مدل جدید روشه خودش رو برای `Clean` و `Dry` انجام میده. ولی ساختن مدل به این روش تمیز نیست. بیاین یکم ساختن مدل هارو ساده تر کنیم. فانکشن `main` نهایتا میشه :

func main() {
   wm := SamsungModel{&quotSM001&quot}
   wm2 := LGModel{&quotLG001&quot, 2020}

   models := []WashingMachine{wm, wm2}

   fmt.Println(models[0].Clean())
   fmt.Println(models[0].Dry())
}



حالا میشه یه فانکشن نوشت که هر ۲ مدل بتونن ازش استفاده کنن والی جز اینترفیس نباشه:

...

func list(wm WashingMachine) {
   fmt.Println(wm.Clean())
   fmt.Println(wm.Dry())
}

func main() {
   wm := SamsungModel{&quotSM001&quot}
   var v WashingMachine = wm

   list(v)
}