11

編集++:

Goでコードを繰り返さないようにするには?

type Animal interface {
    Kingdom() string
    Phylum() string
    Family() string
}

type Wolf struct {}
type Tiger struct {}

func (w Wolf) Kingdom() string {return "Animalia"}
func (w Wolf) Phylum() string {return "Chordata"}
func (w Wolf) Family() string {return "Canidae"}

タイプ用に 3 つのメソッドを実装しましたが、インターフェイスを実装するには、タイプWolf用のすべてのメソッドを実装する必要がありTigerます。ただしKingdomPhylumメソッドは両方のタイプで同じです。Familyタイプのメソッドのみを実装することはどういうわけか可能ですかTiger:

func (t Tiger) Family() string {return "Felidae"}

タイプごとに 3 つの方法をすべて繰り返さないようにするにはどうすればよいでしょうか。

免責事項

メソッド内の単純な文字列の戻り値と混同しないでください。実際のケースでは、定義済みの値だけでなく、さまざまなメソッドの実装が必要です。このばかげたスタイルを使用して、私はあなたの脳を汚すことを避けたい. したがって、スキップメソッドはまったく方法ではありません。ありがとう

4

3 に答える 3

14

これは古典的な構成です:

type Wolf struct {
    Animalia
    Chordata
    Canidae
}
type Tiger struct {
    Animalia
    Chordata
    Felidae
}

type Animalia struct{}

func (Animalia) Kingdom() string { return "Animalia" }

type Chordata struct{}

func (Chordata) Phylum() string { return "Chordata" }

type Canidae struct{}

func (Canidae) Family() string { return "Canidae" }

type Felidae struct{}

func (Felidae) Family() string { return "Felidae" }

func main() {
    w := Wolf{}
    t := Tiger{}
    fmt.Println(w.Kingdom(), w.Phylum(), w.Family())
    fmt.Println(t.Kingdom(), t.Phylum(), t.Family())
}

プレイグラウンド: https://play.golang.org/p/Jp22N2IuHL .

于 2016-10-25T14:10:40.247 に答える
4

これは、インターフェイスの誤用によく似ています。インターフェイスはクラスの代わりではありません。それらは型ができることの表現です。ここにあるのはデータです。構造体にデータを格納します。

type Animal struct {
    kingdom string
    phylum  string
    family  string
}

var wolf = Animal{"Animalia", "Chordata", "Canidae"}
var tiger = wolf
tiger.family = "Felidae"
于 2016-10-25T14:08:51.040 に答える
3

この機能に興味があるので、このトピックに関するいくつかの記事を読み、いくつかの参照ポイントにまとめました。

埋め込み

「埋め込み」という機能。そして、メソッドの実装を繰り返すことで問題を解決します。基本構文:

type Person struct {
    Name string
}

type Speaker struct { // Speaker is an abstract concept it has no name
    *Person // There is a type without field name. It is Anonymous.
}

ラッピングとデコレーション

はい、OOP はありませんが、とにかくコードは DRY でなければなりません。この機能について考える最も明確な方法は、これを構造体をメソッドでラップするものと見なすことです。したがって、匿名フィールドを記述する最も正確な方法は、「decorator」パターン (Pythonistas でよく知られている) です。

func (a *Speaker) Introduce(){ // But speaker can introduce itself
    fmt.Println(a.Name) // We have direct access to a wrapped struct attributes.
}

結合とオーバーライド

また、構造体に実装されたメソッドを組み合わせることができます

func (s Speaker) Speak() string {
    return "Blah-blah"
}

type Den struct { // Combine Person and Speaker under Den struct
    Person
    Speaker
}

func (d Den) Speak() string { // Override Speak method only for Dennis 
    return "I'm quit!"
}

func main() {
    den := Den{Person: Person{Name: "Dennis",}}
    mike := Speaker{Person: Person{Name: "Michael",}}

    fmt.Println(den.Introduce())
    fmt.Println(den.Speak())
    fmt.Println(mike.Introduce())
    fmt.Println(mike.Speak())
}

このようにして、各タイプに必要な各メソッドの実装を回避できます。

インターフェース

インターフェイスと同じこと。しかし、いくつかのインターフェースが組み合わされている場合、使用されているインターフェースで既に宣言されているメソッドを宣言する必要がないということです。

遊び場

Dennis Suratna のブログ記事

ドキュメント

于 2016-10-26T11:49:35.690 に答える