Konu geçmişi:
Go, duck typing'e dayanan basit ama güçlü bir yöntem ve arayüz konsepti geliştirmiştir. Yöntemler sadece adlandırılmış türlere (struct veya alias) eklenebilirken, arayüzler bir dizi yöntemden oluşur. Bu, uygulama için polimorfizm ve soyutlama sağlar, implements ifadesinin açıkça belirtilmesine gerek kalmaz.
Problemler:
Java veya C#'dan gelen programcılar, genellikle implements veya extends ifadelerinin açıkça kullanılmasını beklerler ve değer ve işaretçi ile alıcı (receiver) arasındaki farklılıklarda kafaları karışır; bu da arayüzlerin uygulanmasında öngörülemeyen davranışlar ve hatalara yol açar.
Çözüm:
Yöntem ve arayüz tanımı:
type User struct { Name string } func (u User) Greet() string { return "Hello, " + u.Name } func (u *User) SetName(name string) { u.Name = name } type Greeter interface { Greet() string }
Ana özellikler:
Temel tür int veya string için tür-aliası üzerine yöntemler tanımlamak mümkün mü?
Evet, eğer bu adlandırılmış bir tür ise, örneğin:
type MyInt int func (m MyInt) Double() int { return int(m) * 2 }
Alıcı olarak işaretçi ve değer ile arayüzün uygulanması arasındaki fark nedir?
Eğer arayüz yöntemi (T) olarak tanımlanmışsa, hem T hem de *T arayüzü uygular. Eğer (*T) olarak tanımlanmışsa, yalnızca *T arayüzü tatmin eder. Bu, yapıyı arayüz kabul eden fonksiyonlara geçerken kritiktir.
Arayüz için "zero value" nasıl çalışır ve nil-değerinde bir yöntemi çağırırsanız ne olur?
Başlatılmamış bir arayüz değişkeni nil'ye eşittir, nil'le bir yöntemi çağırma girişimi, nil-pointer'ı işlemek için açık bir işleme bulunmadığı sürece panik yapar.
Yapı, işaretçi yöntemiyle (*T) tanımlandığında, arayüz değer yöntemi (T) bekler ve yapı arayüzlerde kullanılmaya çalışıldığında derlenmez. []User türü yerine User türü için bir yöntem tanımlama girişimi.
Artıları:
Eksileri:
Arayüzleri uygulayan tüm yöntemler doğru alıcı ile tanımlanmıştır. Gerekmedikçe arayüz kullanılmaz (mümkün olduğunda somut tür, gerekirse polimorfizm).
Artıları:
Eksileri: