回答:
彼は、次の順序で何かを使用することを意味します。
class A : public B {};
JavaやC ++のようなもので、Goで使用するもの(同等のもの):
class A {
B b;
};
はい、これは継承のような機能を提供します。上記の例を少し拡張してみましょう。
struct B {
int foo() {}
};
struct A {
B b;
};
A a;
a.foo(); // not allowed in C++ or Java, but allowed in Go.
ただし、これを行うには、C ++またはJavaで許可されていない構文を使用します。埋め込みオブジェクトを独自の名前なしで残すため、次のようになります。
struct A {
B;
};
Goでは、OOPは実際にはありません。
オブジェクトを「特化」したい場合は、埋め込みによって構成しますが、これは構成ですが、いくつかの利点を備えており、部分的に継承に似ています。このようにします:
type ConnexionMysql struct {
*sql.DB
}
このサンプルでは、ConnexionMysqlは* sql.DBの特殊化であり、ConnexionMysqlで* sql.DBで定義されている関数を呼び出すことができます。
type BaseMysql struct {
user string
password string
database string
}
func (store *BaseMysql) DB() (ConnexionMysql, error) {
db, err := sql.Open("mymysql", store.database+"/"+store.user+"/"+store.password)
return ConnexionMysql{db}, err
}
func (con ConnexionMysql) EtatBraldun(idBraldun uint) (*EtatBraldun, error) {
row := con.QueryRow("select pv, pvmax, pa, tour, dla, faim from compte where id=?", idBraldun)
// stuff
return nil, err
}
// somewhere else:
con, err := ms.bd.DB()
defer con.Close()
// ...
somethings, err = con.EtatBraldun(id)
したがって、一見すると、この構成は通常の分類法を作成するためのツールであると考えるかもしれません。
だが
* sql.DBで定義された関数が* sql.DBで定義された他の関数を呼び出す場合、ConnexionMysqlで再定義された関数が存在しても呼び出しません。
古典的な継承では、次のようなことがよく行われます。
func (db *sql.DB) doComplexThing() {
db.doSimpleThing()
db.doAnotherSimpleThing()
}
func (db *sql.DB) doSimpleThing() {
// standard implementation, that we expect to override
}
つまりdoComplexThing
、特殊化の呼び出しに関する組織としてスーパークラスで定義します。
しかし、Goでは、これは特殊な関数ではなく「スーパークラス」関数を呼び出します。
そのため、* sql.DBで定義されているがConnexionMySQL(または他の専門分野)で再定義されている関数を呼び出す必要があるアルゴリズムが必要な場合、このアルゴリズムを* sql.DBの関数として定義することはできませんが、他の場所で定義する必要がありますそして、この関数は提供された特殊化への呼び出しのみを構成します。
インターフェイスを使用してこのようにすることができます:
type interface SimpleThingDoer {
doSimpleThing()
doAnotherSimpleThing()
}
func doComplexThing(db SimpleThingDoer) {
db.doSimpleThing()
db.doAnotherSimpleThing()
}
func (db *sql.DB) doSimpleThing() {
// standard implementation, that we expect to override
}
func (db ConnexionMySQL) doSimpleThing() {
// other implemenation
}
これは、クラス階層の古典的なオーバーライドとはまったく異なります。
特に、2番目のレベルから関数の実装を継承する3番目のレベルを直接持つことはできません。
実際には、ほとんどの(直交)インターフェースの使用を終了し、実装の「スーパークラス」がそれらの呼び出しを整理するのではなく、提供された実装で関数に呼び出しを構成させます。
私の経験では、これにより、1レベルよりも深い階層が実質的に存在しなくなります。
多くの場合、他の言語では、概念Aが概念Bの特殊化であることがわかると、クラスBとクラスAをBのサブクラスとして作成することでこの事実を具体化する反射があります。データをプログラムする場合、これが現実であるという原則に基づいて、コード内のオブジェクトの分類法を再現することに時間を費やします。
Goでは、一般的なアルゴリズムを定義して特殊化することはできません。一般的なアルゴリズムを定義し、それが一般的であり、提供されたインターフェース実装で動作することを確認する必要があります。
ロジックが最終的にすべてのレベルを暗示するアルゴリズムに対応するためにコーダーが複雑なハッキングを行っていた階層ツリーの複雑さが増していることに恐怖を感じていたので、たとえ単純なGoロジックに満足していると思いますアプリケーションモデルの概念を単に具体化するのではなく、考える必要があります。