ページ

2009年11月19日

今更ながらGoのinterfaceとかstructとか・・・

Emacsのバッファにinterfaceとかstructとかをいろいろ試した時のコードがありました。ついでなので、載せておきます。

まずは、interface。interfaceって何かというとPython3のabcみたいなものです。えっ、わかんない?C++の純粋仮想クラスみたいなものです。えっ、だめ?Javaのinterfaceみたいなものです。
こんな感じで書きます
type MyInterface interface {
    Say() string;
}
Javaと同じで、interfaceに直接実装することができません。メソッドを定義できるかです。では、Javaのclass相当のことをするには、structを使います。基本的には、javaのfield値を指定します。
type MyStructBase struct {
    mesg string;
}
structに対してメソッドはfunc (self *MyStructBase) Say() string { return self.mesg; }のように書けば、このSayはMyStructBaseのメソッドになります。じゃあ、interfaceはどこよ?と言うことで、次のような関数を定義します。
func SaySomething(obj MyInterface) {
    mesg = obj.Say();
    fmt.Print(mesg + "¥n");
}
これは、引数にMyInerfaceという型のinterfaceを受け取ります。これを利用する側は、
obj := new(MyStructBase);
obj.mesg = "my struct base";
SaySomething(obj);
という感じです。SaySomethingの引数のMyInterface型のobjは、単にそのinterfaceが定義している関数をobjが持っているかどうかだけをチェックしています。だからduck typingなんですね。と言うか、いい加減なんですね。ちなみに、実行結果は"my struct base"と出力されるはずです。

次にMyStructBaseを継承したようなMyStructExtendを作ってみましょう。
type MyStructExtend struct {
    MyStructBase;
}
structのメンバーを書くところに直接基底クラスみたいなものを書きます。使うときは
obj := new(MyStructExtend);
obj.mesg = "my struct base";
SaySomething(obj);
です。実行結果も"my struct base"となります。MyStructBaseの実装がそのまま使えました
では、MyStructExtendに同じメソッドを追加します。func (self *MyStructExtend) Say() string { return self.mesg + "from MyStructExtend"; }
これを実行すると、"my struct base from MyStructExtend" となります。Javaのsuperみたいなことをするには、
func (self *MyStructExtend) Say() string {
    return self.MyStructBase.Say();
}
とします。これで、継承元のSay関数が呼び出されます。言語オタクはいろいろ言うかもしれませんが、僕は嫌いじゃないです。PythonなどのLLも外界との境界線上にはtype check(もしくは型宣言)があった方がいいと思っているので、このぐらいのいい加減さがいいです。

もっと、テスト用のコードを書いたんだけど、めんどいので、このぐらいで。

0 件のコメント: