2

私は現在、いくつかの go コードをいじっていますが、満足のいく答えが見つからない埋め込みに関する小さな問題に遭遇しました。一方が他方を埋め込み、インターフェイスを満たす 2 つの型が与えられた場合、オブジェクトがデフォルトの応答を提供するために埋め込み型のプロパティを反映できるようにしたいと考えています。オーバーライドしたい場合を除いて、インターフェース内のすべてのメソッドを定義します。

以下のおもちゃの例では、デフォルトのケースを処理し、名前を返すだけの hello() func を組み込みで定義できるようにしたいと考えています (NB これはおもちゃの例であり、実際のコードはより複雑で便利です)。オブジェクトがインターフェイスのすべてのメソッドを明示的に定義する必要があります。実際のコードでは、リフレクションを使用してオブジェクト型のクラス名と構成名を推測しています。現在、型のインスタンスを渡す基底クラス ヘルパーを呼び出していますが、これは満足のいくものではありません。

package main
type MyInterface interface {
    hello() string
    //...
}

type Embedded struct {

}

func (e *Embedded) hello() string {
    name := "none"
    // Would like to be able to return name of object here *if* embedded
    // What's the best approach to tackle this?

    return name
}


type Object struct {
    *Embedded
    Name    string
}

/*
// Would like an *optional* override, with default being embedded somehow replying with data from Object
func (o *Object) hello() string {
    return o.Name
}
*/


func main() {
    o := &Object{Name:"My Object Name"}
    println("Hello world",o.hello())
}

ゴープレイで:

http://play.golang.org/p/ClOOCef9Zb

この種の問題に移動する (埋め込みクラスのプロパティを使用するデフォルト関数を提供する) の他の解決策と、この特定の問題の解決策 (存在する場合) について知りたいと思います。これまでのところ、唯一の解決策は次のいずれかです。

このインターフェイスを満たすすべてのタイプでメソッド hello() の再定義を要求し、デフォルト メソッドを提供する「ベース」クラスを持つことをあきらめる オブジェクト インスタンスへのポインタを使用して埋め込みヘルパー関数を呼び出すので、タイプは呼び出しを行うほとんど空のメソッドを持つことができます埋め込みタイプ。

Goで価値があり、継承モデルを複製しようとしない完全に異なるアプローチがある場合、それらについて聞いてみたいと思います。これまでのところ、継承で見逃したのはこれだけです...

4

2 に答える 2

2

メソッドのレシーバーは / であり、それぞれの型 T のインスタンスを参照します。たとえば、T のメソッドの実行中に U に埋め込まれている T に関する情報を取得する方法は、言語でサポートされていません。

type (
        T foo
        U struct {
                t T
                f baz
        }
)

func bar() {
        var t T
        var u U
        t.foo()
        u.t.foo()
}

func (t T) foo()  {} // t might be or be not embeded in u
func (t *T) qux() {} // *t might be or be not embeded in u

おそらく構造継承を使用しようとしています。それはサポートされていません。埋め込みによる型の合成はありますが、それはクラス階層に類似したものではありません。

OTOH、Go インターフェイスは継承とメソッドのオーバーライドをサポートしているので、それがその方法かもしれません。この場合、継承は構造的ではなく動作的であることに注意してください。

于 2013-03-17T11:49:50.640 に答える
0

これに取り組むために、ersatz 継承を捨てて、モデルがインターフェイスで共有する必要がある情報を指定することにしました (ここでフィールドの自動属性アクセサーがないのは少し面倒です。上記のオブジェクトは、許可するためにこれらを明示的にエクスポートする必要があります)。それらを使用するために MyInterface ref を渡す人、フィールド Name は public ですが、Name() 文字列が Interface で定義されている場合でもアクセスできません)。

次に、モデルは別のパッケージのヘルパー関数を呼び出し、それ自体が便利なパラメーターとして提供されます。MyInterface に準拠しているため、そのように問い合わせることができます。そのため、それ (およびそのような他の MyInterface オブジェクト) は、公開情報を使用して複雑な操作を実行し、ファサードとして機能することができます。上記の簡単な例では明らかに無意味ですが、パッケージのコードをいくつかの MyInterface タイプ間で共有したかったので、埋め込みではなくこのアプローチを使用します。

したがって、上記の jnml で指摘されているように、ここでの主なポイントは、埋め込みはインスタンスの状態に依存する関数を混在させるのには役に立たず、継承階層の基本クラスを直接置き換えるものではないということです。Go をしばらく使用している場合は、おそらく明らかです...

于 2013-03-18T23:13:19.187 に答える