Goのinterfaceと他の言語(Swift/ObjC/Java/PHP)での(明示的)実装方法

1 Star2 Stars3 Stars4 Stars5 Stars (まだ評価されていません)
Loading...

Goではインターフェース型で実装された関数を全て実装すれば、その型で振舞うことができます。

ダック・タイピングなアプローチができるので、これが扱えるのと扱えないのではコードに差が出てくるなと感じます。

一旦慣れてしまえば簡単に使えるのですが、わからない人向けに感覚値として掴んでもらえればと思って明示的な方法でインターフェースの実装を他の言語に置き換えています。

https://github.com/kaneshin/sample-interfaces

Goのファイルに関して、今回はインターフェースを埋め込んでいるため、仮にSounds関数を実装していなくてもビルドが通ります。

ですが、もちろんのこと実装していないため、ランタイムエラーとなります。

そこの違いもいろいろ触ってもらえればと。(ビルドエラーかランタイムエラーか、実装変えるとどうなるかなどなど)

一部だけ解説します。

Goでは宣言したinterfaceの実装さえされていれば、その型で振舞われるため、わざわざインターフェースを埋め込まなくてもよいです。
よくわからないければ、作り手の意思としてチョイスする感じでよいかと。(適当)

package main
import "fmt"
type Animal interface {
sounds() string
}
type Cat struct {
Animal
Name string
}
func (c Cat) sounds() string {
return "Meow"
}
func call(a Animal) {
fmt.Println(a.sounds())
}
func main() {
cat := Cat{Name: "NyanCat"}
call(cat)
}

Swiftのprotocolでは、Objective-C時代にあった@optionalにあたるものがなくなりました。

そのため、protocol実装されたオブジェクトに関して必ず実装する必要があるため、ランタイムエラーとなり得る実装は無理な気がしました。柔軟ではないですね。(さすが堅牢をうたっているだけある(褒めてます。褒めてます。


protocol Animal {
func sounds() -> String
}
struct Cat: Animal {
var name: String
init(name: String) {
self.name = name
}
func sounds() -> String {
return "Meow"
}
}
func call(a : Animal) {
println(a.sounds())
}
func main() {
var cat = Cat(name: "NyanCat")
call(cat)
}
main()

Objective-Cには@optionalがあるため、- (NSString *)sounds;を実装しなくてもビルドが通ります。
が、もちろんメソッドがない場合はランタイムエラーとなります。

#import <Foundation/Foundation.h>
@protocol Animal
@optional
- (NSString *)sounds;
@end
@interface Cat : NSObject <Animal>
@property (nonatomic, strong) NSString *name;
@end
@implementation Cat
- (NSString *)sounds {
return @"Meow";
}
@end
void call(NSObject<Animal> *a) {
printf("%s\n", [[a sounds] UTF8String]);
}
int main(int argc, char *argv[])
{
Cat *cat = [Cat new];
cat.name = @"NyanCat";
call(cat);
return 0;
}


1 Star2 Stars3 Stars4 Stars5 Stars (まだ評価されていません)
Loading...
      この投稿は審査処理中  | 元のサイトへ