Answers:
他的意思是您将按照以下顺序使用某些东西:
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的函数,而必须在其他位置定义它并且此函数将仅构成对所提供专业化的调用。
您可以使用interfaces这样做:
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
}
这与经典的类层次结构的重写有很大不同。
特别是,您显然不能直接让第三级继承第二级的函数实现。
在实践中,您将最终使用大多数(正交)接口,并让函数在提供的实现上编写调用,而不是让实现的“超类”来组织这些调用。
以我的经验,这实际上导致了层次结构的深层缺失。
通常,在其他语言中,当您看到概念A是概念B的专门化时,就会产生反省,可以通过创建类B和类A作为B的子类来证实这一事实。在围绕数据的程序上,您花时间重现代码中对象的分类法,这是事实。
在Go中,您无法定义通用算法并将其专用化。您必须定义一个通用算法并确保它是通用算法,并且可以与提供的接口实现一起使用。
由于某些层次结构树的复杂性不断增长而感到震惊,编码人员在这些复杂树上进行复杂的破解以尝试适应一种逻辑最终暗示所有层次的算法,我想说我对更简单的Go逻辑感到满意,即使它迫使您要思考,而不仅仅是重新定义应用程序模型的概念。