1 回答
TA贡献1876条经验 获得超7个赞
技术说明:第一种方法向您保证(除了初始化结构时的错误)您可以调用methodAon Bar,第二种方法则不能,因为您必须使用与该接口相关的东西来初始化接口字段,以免出现 nil deference 错误。
请注意,使用第二种方法methodA不是在嵌入式对象上调用Bar ,而是在Foo嵌入对象上调用!
如果你有一个可以由许多对象共享并且是自包含的公共实现,则第二种方法很有用,即考虑你想知道一个对象是否实现了一个方法以确保你可以使用该对象记录一些东西Log:在这种情况下你可以有一个返回 aLogger并用它设置接口字段的方法。示例如下:
package main
import "fmt"
type Logger interface {
Log(string)
}
type ConsoleLogger struct {} // See? No external dependencies
func (Cl ConsoleLogger) Log(msg string) {
fmt.Println(msg)
}
type A1 struct {
Logger
}
type A2 struct {
Logger
}
func main() {
a := A1{ConsoleLogger{}}
b := A2{ConsoleLogger{}}
a.Log("Test")
b.Log("Test")
}
嵌入对象对于调度方法调用很有用,请记住它最终只是语法糖,所以除了传递包含对象之外,您没有任何方法可以使用它的字段。
如果接口必须以某种方式使用外部对象 ( 和 ) 数据,那么此方法会很尴尬,因为您必须初始化接口对象,然后在某些情况下会浪费内存来存储对所需数据的一些Logger引用A1。A2
恕我直言,方法一会强制您编写更多代码,但您在接口实现中更加自由,您可以通过嵌入 aLogger然后重写结构Log中的方法来混合这两种方法A1。
此外,您仍然可以传递一些东西来构建实现接口的东西:
package main
import "fmt"
type Logger interface {
Log(string)
}
type ConsoleLogger struct {
Prepend string // string to prepend to log message
}
func (Cl ConsoleLogger) Log(msg string) {
fmt.Println(Cl.Prepend + "-" + msg)
}
type A1 struct {
Logger
}
type A2 struct {
Logger
}
func (a A2) Log(msg string) { // Overriding implementation
fmt.Println("In A2")
a.Logger.Log(msg) // Call the original interface value!
}
func main() {
a := A1{ConsoleLogger{"A1"}}
b := A2{ConsoleLogger{"A2"}}
a.Log("Test")
b.Log("Test")
}
- 1 回答
- 0 关注
- 74 浏览
添加回答
举报