2016-05-17 7 views
2

私はハンドラを受け入れる型を実装し、必要なときに呼び出す型を実装するライブラリを使っています。私は型を埋め込んだスーパータイプを作成したいのですが、埋め込み型以外のプロパティを持っています。 そして、これらのプロパティをハンドラで使用できるようにしたいと思います。ハンドラ関数があるときに型を埋め込む方法は?

引数として自分の型を使用すると、型チェックに失敗します。ハンドラdeclの基本型を使用しても、新しいフィールドにアクセスすることはできません。私は(DECLハンドラインタフェースの代わりに?)行くのは新しいです、&がこれを行う方法を知ってみたい、または有効にするには、ライブラリを変更するに示唆するのか...

不自然な例:

package main 

    type Animal struct { 
     Color string 
     feeders map[string]feeder 
    } 
    type feeder func(*Animal, string) string 

    func (a *Animal) addFeeder(name string, fn feeder) { 
     a.feeders[name] = fn 
    } 

    type mamal struct { 
     Animal 
     hair string 
    } 

    func feedHuman(m *mamal, food string) string { 
     return "you got " + m.Color + " " + m.hair + " hair in your " + food 
    } 

    func main() { 
     a := mamal{Animal{Color: "red"}, "bushy"} 
     a.addFeeder("man", feedHuman) 
     // fails to compile feedHuman needs to take *Animal but then cant access hair" 
    } 

答えて

0

あなたはそうです、ママは動物ではないので、あなたはそれをすることはできません。それは解決策ではありませんので、継承はありません。しかし、この振る舞いはインターフェイスで実現できます。ちなみにフィーダーマップを初期化していないためコードが機能しないため、コンパイル後に問題が発生します。

解決方法1:使用タイプアサーション

package main 

import "fmt" 

type Animal struct { 
    Color string 
    feeders map[string]feeder 
} 
type feeder func(interface{}, string) string 

func (a *Animal) addFeeder(name string, fn feeder) { 
    a.feeders[name] = fn 
} 

type mamal struct { 
    Animal 
    hair string 
} 

func feedHuman(i interface{}, food string) string { 
    m := i.(mamal) 
    return "you got " + m.Color + " " + m.hair + " hair in your " + food 
} 

func main() { 
    a := mamal{Animal{feeders: make(map[string]feeder), Color: "red"}, "bushy"} 
    a.addFeeder("man", feedHuman) 
    fmt.Println(a.feeders["man"](a, "pineapple")) 
    // => you got red bushy hair in your pineapple 
} 

あなたが渡すインタフェースがmamalでない場合、それはパニックになりますので、これは少し危険です。

第二ソリューション:それは同じように正常に動作しますが、それは一つにハンドラの数を制限しますので、私は、これはあなたが求める何だとは思わない

package main 

import "fmt" 

type Feeder interface { 
    Feed(string) string 
} 

type Animal struct { 
    Color string 
    feeders map[string]Feeder 
} 

func (a *Animal) addFeeder(name string, feeder Feeder) { 
    a.feeders[name] = feeder 
} 

type mamal struct { 
    Animal 
    hair string 
} 

func (m *mamal) Feed(food string) string { 
    return "you got " + m.Color + " " + m.hair + " hair in your " + food 
} 

func main() { 
    a := &mamal{Animal{Color: "red", feeders: make(map[string]Feeder)}, "bushy"} 
    a.addFeeder("man", a) 
    fmt.Println(a.feeders["man"].Feed("pineapple")) 
    // you got red bushy hair in your pineapple 
} 

フィーダーインタフェースを使用してください。

+0

私は#2がアイデアと一致しないことに同意します。 #1は約束しているが、ライブラリの他のすべてのユーザーを壊す。だから、私はインターフェイス{}を持つ新しいジェネリックハンドラアダーを提案し、それを呼び出すために現在のものを変更します。だから、ベースフォームは一般的ですが、外部インターフェイスは、タイプを拡張しない人のために同じままです。 https://play.golang.org/p/QIZ90CiHFu – Blaize

+0

喜んで助けました。あなたの新しいソリューションがあなたのニーズに合っていれば、それは問題ありません。 –

関連する問題