「Go/メソッドとインターフェース」の版間の差分
削除された内容 追加された内容
Semi-Brace (トーク | 投稿記録) Go 版176949から分割 |
→メソッド: Goはオブジェクト指向言語ではないのでしょうか? タグ: 2017年版ソースエディター |
||
1 行
== メソッド ==
Goには、C++やJavaのようなクラスベースオブジェクト指向言語にあるような class はありません。
またGoには、JavaScript, LuaやSelfのようなプロタイプベースオブジェクト指向言語にあるようなプロトタイプチェーンもありません。
Goがオブジェクト指向言語かの議論は、オブジェクト指向言語の定義に還元されすので興味深いのですが、ここでは結論を出しません。
さてタイトルの'''メソッド'''ですが、多くのオブジェクト指向言語で備えている関数の特別な形式で
オブジェクト.メソッド(引数)
の形式を取るものが多くみられます。
Go言語では、型と結びついたメソッドを作成できます。
;[https://paiza.io/projects/q_nEtbtbs0XU0L6Zaflz6A?language=go コード例]:<syntaxhighlight lang="go" highlight="5,7-9,13,14" line>
package main
import
type
func (n
return n * n
}
func main() {
n := Number(7)
m := n.pow()
fmt.Printf("%v(%T)\n", m, m)
}
</syntaxhighlight>
;実行結果:<syntaxhighlight lang=text>
49(main.Number)
</syntaxhighlight >
;解説:<syntaxhighlight lang="go" start=5 line>
type Number int
</syntaxhighlight>
:組込み型にはメソッドは定義できず、型定義が必要です(この場合は Number)。
;メソッド定義:<syntaxhighlight lang="go" start=7 line>
func (n Number) pow() Number {
return n * n
}
</syntaxhighlight>
:<code>(n Number)</code> がレシーバーで、<code>pow</code> がメソッド名です。
:レシーバーがあることが関数との違いで、それは呼び出し方法にもあります。
;メソッドの呼び出し:<syntaxhighlight lang="go" start=13 line>
m := n.pow()
</syntaxhighlight>
: [[Go/定数と変数#短い変数宣言|短い変数宣言]]の構文です。
: <code>n.pow()</code> がメソッドコールで、関数コールにはない <code>n.</code> がメソッド独特なレシーバーです。
: <syntaxhighlight lang="go" start=7 line inline> func (n Number) pow() Number { return n * n } </syntaxhighlight> の戻り値の型も Number なので、m の型は Number と型推論されます。
;fmt.Printfで表示:<syntaxhighlight lang="go" start=14 line>
fmt.Printf("%v(%T)\n", m, m)
</syntaxhighlight>
:C言語のprintf()にはない型指定子 <code>%v</code>(値を表示)と <code>%T</code>(型名を表示)を使っています。
::「なぜユーザー定義型の型名を知っているのか?」
:というのが最もな疑問だと思います。
: ライブラリーのソースコード go/src/fmt/print.go を読むのが最適なのですが、結論から言うと '''reflect''' パッケージの <code>TypeOf</code> 関数を呼び出しています。
: <code>reflect.TypeOf</code> は go/src/reflect/type.go で定義されています。
: この様に、GoのパッケージはGo自身で書かれていますし、go(コンパイラーやパッケージマネージャーのフロントエンド)もGoで書かれているので、コーディング例の宝庫と言えます。
== インターフェース ==
|