转到界面 return 类型
Go interface return type
我有这样的界面:
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{})
}
但是我得到这个错误:
cannot use MainView literal (type MainView) as type ViewInterface in
argument to Render: MainView does not implement ViewInterface (wrong
type for Init method)
have Init() MainView
want Init() View
为什么 MianView
和 View
不一样?解决这个问题的正确方法是什么?
谢谢
与 Java 和 C# 等主流语言相比,Go 具有不同的继承模型。
Why MianView is not same as View?
因为定义不同
Init
MainView
returns MainView
的功能而接口需要 return View
.
Init
方法的签名看起来很奇怪,它需要结构实例,因为它是结构方法和 return 相同结构类型的新实例。
尝试围绕结构逻辑而不是结构逻辑设计界面 construction/lifetime:
type ViewInterface interface{
Render()
}
type MainView View
func (m MainView) Render() {
// do something
}
type AnotherView
func (m AnotherView) Render() {
// do something else
}
func Render(views ...ViewInterface){
for _, view := range views {
view.Render()
}
}
因为type MainView View
是一个"defined type" and "is different from any other type, including the type it is created from.".
您可以使用 type alias。 type MainView = View
.
但真正的问题是 ViewInterface
和 Init()
的设计。
Init()
写成 class 方法。 Go 没有 class 方法(或者,严格来说,classes)。您创建结构并在其上调用方法。简单的初始化就可以马上完成。
view := View{ Width: 10, Height: 10 }
如果你想定义一个方法来一致地初始化值,它会作用于一个现有的结构,return什么都没有。
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)
}
然后 aRender()
可以获取实现 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)
}
最后, 使用一个包来获得类似 class 方法的东西。
# 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.
我有这样的界面:
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{})
}
但是我得到这个错误:
cannot use MainView literal (type MainView) as type ViewInterface in argument to Render: MainView does not implement ViewInterface (wrong type for Init method)
have Init() MainView
want Init() View
为什么 MianView
和 View
不一样?解决这个问题的正确方法是什么?
谢谢
与 Java 和 C# 等主流语言相比,Go 具有不同的继承模型。
Why MianView is not same as View?
因为定义不同
Init
MainView
returns MainView
的功能而接口需要 return View
.
Init
方法的签名看起来很奇怪,它需要结构实例,因为它是结构方法和 return 相同结构类型的新实例。
尝试围绕结构逻辑而不是结构逻辑设计界面 construction/lifetime:
type ViewInterface interface{
Render()
}
type MainView View
func (m MainView) Render() {
// do something
}
type AnotherView
func (m AnotherView) Render() {
// do something else
}
func Render(views ...ViewInterface){
for _, view := range views {
view.Render()
}
}
因为type MainView View
是一个"defined type" and "is different from any other type, including the type it is created from.".
您可以使用 type alias。 type MainView = View
.
但真正的问题是 ViewInterface
和 Init()
的设计。
Init()
写成 class 方法。 Go 没有 class 方法(或者,严格来说,classes)。您创建结构并在其上调用方法。简单的初始化就可以马上完成。
view := View{ Width: 10, Height: 10 }
如果你想定义一个方法来一致地初始化值,它会作用于一个现有的结构,return什么都没有。
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)
}
然后 aRender()
可以获取实现 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)
}
最后,
# 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.