我有这样的界面:
type ViewInterface interface{
Init() View
}
type View struct{
Width int
Height int
}
所以我从View创建一个新类型
type MainView View
func (m MainView) Init() MainView{
return MainView{
Width:10,
Height:10,
}
}
然后将MainView传递给以下方法:
func Render(views ...ViewInterface){
for _, view := range views {
v := view.Init()
}
}
func main() {
Render(MainView{})
}
但是我得到这个错误:
不能使用MainView文字(MainView类型)作为ViewInterface类型 Render的参数:MainView不实现ViewInterface(错误 方法的类型)
具有Init()MainView
想要Init()查看
为什么MianView
与View
不同?解决这个问题的正确方法是什么?
谢谢
答案 0 :(得分:6)
与Java和C#等主流语言相比,GO具有不同的继承模型。
为什么MianView与View不同?
因为它们的定义不同。
Init
的{{1}}函数返回MainView
,而接口要求返回MainView
。
View
方法的签名看起来很奇怪,它需要结构实例,因为它是结构方法并返回相同结构类型的新实例。
尝试围绕结构的逻辑而非结构/寿命设计接口:
Init
答案 1 :(得分:4)
因为type MainView View
是"defined type"和"is different from any other type, including the type it is created from."。
您可以使用type alias。 type MainView = View
。
但是实际上问题是ViewInterface
和Init()
的设计。
Init()
的编写类似于类方法。 Go没有类方法(或者严格来说是类)。您创建结构并在其上调用方法。此时即可完成简单的初始化。
view := View{ Width: 10, Height: 10 }
如果要定义一个方法来一致地初始化值,它将对现有结构起作用,不返回任何内容。
type ViewInterface interface{
Init()
}
type View struct{
Width int
Height int
}
func (v *View) Init() {
v.Width = 10
v.Height = 10
}
view := View{}
view.Init()
然后MainView
也可以定义Init()
。
type MainView struct {
X int
Y int
}
type (mv *MainView) Init() {
mv.X = 23
mv.Y = 42
}
因为Init()
需要一个指针,要满足ViewInterface
,您必须传递指针。
func main() {
view := View{}
mv := MainView{}
Render(&view, &mv)
}
但是Render()
到底在做什么初始化对象?那应该已经完成了。应该是渲染。接口应该是关于通用功能的,而不论其实现方式如何。实现ViewInterface的事物应该已经初始化。
相反,您可能会说ViewInterface
必须具有Render
方法。
type ViewInterface interface{
Render()
}
然后View
和MainView
可以结构化,但是只要它们实现Render()
,就可以根据需要进行构建。
func (v View) Render() {
fmt.Println("View!")
fmt.Println(v)
}
func (mv MainView) Render() {
fmt.Println("MainView!")
fmt.Println(mv)
}
然后,一个Render()
可以列出实现ViewInterface
的事物,并在每个事物上调用Render()
。
func Render(views ...ViewInterface){
for _, view := range views {
view.Render()
}
}
在传递它们之前将它们初始化。现在无需传递指针。
func main() {
view := View{}
view.Init()
mv := MainView{}
mv.Init()
Render(view, mv)
}
最后,Markus suggested in the comments使用包来获取类似类方法的内容。
# viewtest/main.go
package main
import(
"log"
"viewtest/view"
)
func main() {
v := view.New()
log.Printf("%#v", v)
}
# viewtest/view/view.go
package view
type View struct {
Width int
Height int
}
func New() View {
return View{Width: 10, Height: 10}
}
Go软件包需要一点时间来适应,Go对于必须如何构造项目具有明确的想法。 I suggest this tutorial。