Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

13

Share

Download to read offline

インタフェースの実装パターン

Download to read offline

Related Books

Free with a 30 day trial from Scribd

See all

インタフェースの実装パターン

  1. 1. インタフェースの 実装パターン 2014/08/09 (土) @Go lang勉強会
  2. 2. 自己紹介 上田拓也 KLab株式会社 仕事: Webviewと戦う仕事 趣味: Go言語, JS twitter : @tenntenn
  3. 3. はじめに ● このプレゼンは以下の記事をまとめたものです ○ インタフェースの実装パターン ○ http://qiita. com/tenntenn/items/eac962a49c56b2b15 ee8 ● たぶん15分じゃ終わらないので,間に合わな かったら,qiitaを見て下さい
  4. 4. アジェンダ ● typeで型を宣言する ● メソッド ● 基本的なインタフェースの実装 ● 関数にインタフェース実装させる ● 構造体に埋め込んでインタフェースを実装する ● 埋め込みを使ったインタフェースの部分実装 ● 埋め込みを使ったインタフェースの動的実装
  5. 5. typeで型を宣言する
  6. 6. 構造体型とインタフェース型の宣言 // 構造体型の宣言 type Hoge struct { // フィールドリスト } // インタフェース型の宣言 type Fuga interface { // メソッドリスト }
  7. 7. typeを型の宣言の文法 TypeDecl = "type" ( TypeSpec | "(" { TypeSpec ";" } ")" ) . TypeSpec = identifier Type . Type = TypeName | TypeLit | "(" Type ")" . TypeName = identifier | QualifiedIdent . TypeLit = ArrayType | StructType | PointerType | FunctionType | InterfaceType | SliceType | MapType | ChannelType .
  8. 8. typeを型の宣言の文法(ざっくり) ● type 識別子 型 ○ 識別子:型名 ○ 型 ■ 型名 ● int, string, fmt.Stringer ■ 型リテラル ■ (型)
  9. 9. 既存の型に新しい名前をつける ● intに新しくHexという名前をつける type Hex int
  10. 10. 型リテラル ● 配列型  :[10]int ● 構造体型 : struct { /* フィールドリスト */ } ● ポインタ型:*int ● 関数型  :function(s string) int ● インタフェース型: interface { /* メソッドリスト */} ● スライス型:[]int ● マップ型 :map[string]int ● チャネル型:chan bool
  11. 11. 関数型に名前をつけて型を宣言する ● net/httpパッケージのHandlerFuncは関数型にtype で名前をつけたもの type HandlerFunc func(wResponseWriter, r *Request)
  12. 12. メソッド
  13. 13. メソッドの定義方法 // pはレシーバ func (p *Person) String() string { return fmt.Sprintf( "%s %s (%d)", p.FirstName, p.LastName, p.Age, ) } type Person struct { FirstName string LastName string Age int }
  14. 14. 構造体型以外にもメソッドを設ける ● インタフェース型以外なら,どんな型でもレシー バにできる ○ もちろん,型リテラルはダメ type Hex int func (h Hex) String() string { return fmt.Sprintf( "0x%x", int(h), ) }
  15. 15. 関数にメソッドを持たせる type HandlerFunc func( w ResponseWriter, r *Request, ) func (f HandlerFunc) ServeHTTP( w ResponseWriter, r *Request, ) { f(w, r) }
  16. 16. 基本的なインタフェースの実装
  17. 17. インタフェース型の宣言 type TypeName interface { // メソッドリスト Method1() Method2() }
  18. 18. インタフェースの実装 ● メソッドリストのメソッドをすべて実装していれ ば,インタフェースを実装したことになる type Stringer { String() string } // HexはStringerインタフェースを実装 type Hex int func (h Hex) String() string { return fmt.Sprintf("0x%x", int(h)) } 実際に,fmtパッケージで 定義されているインタ フェース
  19. 19. インタフェースの実装 ● int型の100をHex型にキャスト ● fmt.Stringer型の変数に代入して いる var stringer fmt.Stringer stringer = Hex(100)
  20. 20. 関数にインタフェース実装させる
  21. 21. 関数にインタフェース実装させるには ● 関数の型リテラルにtypeで名前をつける ● 作った型にインタフェースで指定されているメ ソッドを設ける
  22. 22. http.HandlerFuncの例 type HandlerFunc func( w ResponseWriter, r *Request, ) func (f HandlerFunc) ServeHTTP( w ResponseWriter, r *Request, ) { f(w, r) }
  23. 23. http.HandlerFuncの例 ● ServeHTTPメソッドを実装していれば,http. Handlerインタフェースを実装したことになる type Handler interface { ServeHTTP( w ResponseWriter, r *Request, ) }
  24. 24. http.HandlerFuncの例 ● 関数をhttp.Hanlderとして振る舞わせる f := http.HandlerFunc(func( w http.ResponseWriter, r *http.Request, ) { fmt.Fprintf(w, "hello, world") }) // 第1引数:pattern string // 第2引数:handler http.Handler http.Handle("/", f)
  25. 25. http.HandlerFuncの例 ● 通常はhttp.HandleFuncを使う ● HandleFunc内では,関数をHandlerFunc型に キャストして,http.Handleを呼んでいる func HandleFunc( pattern string, handler func(ResponseWriter, *Request), )
  26. 26. 構造体に埋め込んでインタフェースを実装する
  27. 27. 埋め込み ● 構造体には匿名フィールドとして,指定した型の 値を埋め込むことができる ● 埋め込んだ値のフィールドやメソッドはあたかも 埋め込み先のフィールドやメソッドのように利用 できる
  28. 28. 埋め込みの例 type Name struct { FirstName string LastName string } func (n *Name) String() string { return fmt.Sprintf("%s %s") } type Person struct { *Name // *Name型の値を埋め込む Age int }
  29. 29. 埋め込みの例 n := &Name{ FirstName: "Taro", LastName: "Yamada", } p := &Person{ Name: n, // *Name型のnを埋め込む Age: 20, } // nのメソッドをpのメソッドのように呼べる fmt.Println(p.String())
  30. 30. 埋め込みによるインタフェースの実装 ● 埋め込んだ値がインタフェースを実装していた 場合,埋め込み先の構造体も,そのインタ フェースを実装したことになる // nがインタフェースを実装しているので, // pもインタフェースを実装したことになる var stringer fmt.Stringer = p fmt.Println(stringer.String())
  31. 31. 埋め込みを使ったインタフェースの部分実装
  32. 32. 複数のメソッドを持つインタフェース ● インタフェースの宣言時に,メソッドリストに複数 のメソッドを指定できる type Person interface { Title() string Name() string }
  33. 33. 一部のメソッドだけ実装させる type person struct { firstName string lastName string } // Nameメソッドだけだと // Personインタフェースは実装したことにならない func (p *person) Name() string { return fmt.Sprintf( "%s %s", p.firstName, p.lastName ) } type Person interface { Title() string Name() string }
  34. 34. 残りは埋め込み先で実装させる type female struct { *person } func (f *female) Title() string { return "Ms." } type male struct { *person } func (m *male) Title() string { return "Mr." }
  35. 35. 実装の切り分けは外部から隠蔽する func NewPerson( gender Gender, firstName, lastName string, ) Person { p := &person{firstName, lastName} if gender == Femail { return &femail{p} } return &male{p} } type Gender int const ( Female = iota Male )
  36. 36. 埋め込みを使ったインタフェースの動的実装
  37. 37. インタフェース型の埋め込み ● 型名がついていればどんな型でも匿名フィール ドにして埋め込むことができる type Hoge struct { chan int // ダメ []int // ダメ fmt.Stringer // OK } 型リテラルは ダメ
  38. 38. インタフェース型の埋め込み func main() { p := Person{ Stringer: nil, FirstName: "Taro", LastName: "Yamada", Age: 20, } fmt.Println(p.Stringer) // nil p.Stringer = ??? } type Person struct { fmt.Stringer FirstName string LastName string Age int } fmt.Stringerインタフェースを実装していれば代入できる
  39. 39. 埋め込む構造体をバインドする ● 埋め込んだインタフェース型の匿名フィールドに インタフェースを実装した値を動的に代入できる ● 代入するインタフェースを実装した値は,埋め込 み先の構造体にアクセスできないと意味がない ○ 埋め込み先を参照できるクロージャにインタフェースを実 装させればよい
  40. 40. 埋め込む構造体をバインドする func BindStringer( p *Person, f func(p *Person) string) fmt.Stringer, { return StringerFunc(func() string { return f(p) }) } type StringerFunc func() string func (sf StringerFunc) String() string { return sf() }
  41. 41. まとめ ● なんでもstructで型を作るのはGo言語っぽくな い ○ typeとメソッドをちゃんとおさえる ● 埋め込みとインタフェースの実装をうまく使う ○ インタフェースの実装を埋め込む値に移譲するパターン ● The Go Programming Language Specificationを見なが ら,黒魔術を考えるの楽しい ○ http://golang.org/ref/spec
  • yusukesaito3

    Sep. 13, 2021
  • tetsuyanh

    Jul. 27, 2018
  • KokiYasuda1

    Jan. 18, 2018
  • WataruUmei

    Oct. 19, 2016
  • hashimotoms

    May. 4, 2015
  • takecy

    May. 4, 2015
  • stylethewalker

    Apr. 28, 2015
  • basabasan

    Feb. 11, 2015
  • objectx

    Aug. 11, 2014
  • teaplanet1

    Aug. 10, 2014
  • takafumitsuchida5

    Aug. 9, 2014
  • hnakamur

    Aug. 9, 2014
  • TokyoIncidents

    Aug. 9, 2014

Views

Total views

5,968

On Slideshare

0

From embeds

0

Number of embeds

266

Actions

Downloads

15

Shares

0

Comments

0

Likes

13

×