下面的代码实际上是不言自明的。
为什么我可以说CreateLion()的结果,一个实现Cat接口的结构的指针,是Cat接口的一个实例,但我不能说CreateLion()的类型为“返回Cat界面。“
实现此类行为的标准Golang方法是什么?
package main
import "fmt"
func main() {
var lion Cat := CreateLion()
lion.Meow()
// this line breaks. Why?
var cf CatFactory = CreateLion
}
type Cat interface {
Meow()
}
type Lion struct {}
func (l Lion) Meow() {
fmt.Println("Roar")
}
// define a functor that returns a Cat interface
type CatFactory func() Cat
// define a function that returns a pointer to a Lion struct
func CreateLion() *Lion {
return &Lion{}
}
答案 0 :(得分:7)
试试这个:
package main
import "fmt"
type Cat interface {
Meow()
}
type Lion struct{}
func (l Lion) Meow() {
fmt.Println("Roar")
}
type CatFactory func() Cat
func CreateLion() Cat {
return Lion{}
}
func main() {
lion := CreateLion()
lion.Meow()
var cf CatFactory = CreateLion
fLion := cf()
fLion.Meow()
}
在大多数情况下,您可以将任何类型分配给基本类型interface{}
。但是,如果函数参数的类型是map[T]interface{}
,[]interface{}
或func() interface{}
,情况会发生变化。
在这种情况下,类型必须相同。
答案 1 :(得分:3)
我认为你应该阅读这篇博文http://blog.golang.org/laws-of-reflection,它确切地说明了变量,类型和接口之间的关系。
在您的示例中,*Lion
与Cat
不同。
您可以更正从CreateLion
到*Lion
的功能Cat
。
答案 2 :(得分:2)
这里的问题是静态类型去区分“这是一个返回猫的函数”,“这是一个返回狮子的函数”,因此不会接受另一个。
解决此问题的方法是为您的工厂提供完全符合预期的工厂:
var cf CatFactory = func() Cat{
return CreateLion()
}
catlion := cf()
catlion.Meow()
答案 3 :(得分:0)
进行一些更改即可正常工作。在此处查看:https://play.golang.org/p/ECSpoOIuzEx
package main
import "fmt"
func main() {
lion := CreateLion() // Go idomatic style recommends
// allowing the compiler to divine the type
lion.Meow()
CatFactory := CreateLion
_ = CatFactory // Go doesn't like unused variables and fails the build
obj := CatFactory() // exercising our factory method
obj.Meow()
}
type Cat interface {
Meow()
}
type Lion struct {}
func (l Lion) Meow() {
fmt.Println("Roar")
}
// define a functor that returns a Cat interface
type CatFactory func() Cat
// define a function that returns a pointer to a Lion struct
func CreateLion() *Lion {
return &Lion{}
}
此外,尽管Go没有Java样式的接口,但它确实具有接口并且可以实现多态,但是类型在编译时就已知。
如果两种类型都实现相同的接口,则可以为“是”关系建模。但是,在将对象传递到接受该接口类型的函数之前,它不会强制执行该接口。因此,如果您想实现策略模式,则在传递策略对象匹配接口“ Cat”时,该函数将接受“ Lion”对象,或任何其他使用正确签名实现Meow函数的类。
此外,工厂方法在Go中绝对必要且有用。实际上,在Go中,您可以使用工厂函数来构造对象,而不是使用构造函数。