我试图在Go上做一些简单的事情:拥有一个带有getter和setter方法的接口。并且似乎不允许使用setter方法。
鉴于此代码:
package main
import "fmt"
type MyInterfacer interface {
Get() int
Set(i int)
}
type MyStruct struct {
data int
}
func (this MyStruct) Get() int {
return this.data
}
func (this MyStruct) Set(i int) {
this.data = i
}
func main() {
s := MyStruct{123}
fmt.Println(s.Get())
s.Set(456)
fmt.Println(s.Get())
var mi MyInterfacer = s
mi.Set(789)
fmt.Println(mi.Get())
}
Set
方法不起作用,因为在func (this MyStruct) Set(i int)
中,this MyStruct
不是指针,并且在函数退出时很快就会丢失更改。但是使this *MyStruct
无法编译。有没有解决方法?
答案 0 :(得分:7)
以下是您的代码的更正版本(playground)。这并不完全是多态性,但使用界面是很好的Go风格。
package main
import "fmt"
type MyInterfacer interface {
Get() int
Set(i int)
}
type MyStruct struct {
data int
}
func (this *MyStruct) Get() int {
return this.data
}
func (this *MyStruct) Set(i int) {
this.data = i
}
func main() {
s := &MyStruct{123}
fmt.Println(s.Get())
s.Set(456)
fmt.Println(s.Get())
var mi MyInterfacer = s
mi.Set(789)
fmt.Println(mi.Get())
}
答案 1 :(得分:4)
我曾经在Go:
中找到了如何进行多态的示例http://play.golang.org/p/6Ip9scm4c3
package main
import "fmt"
type Talker interface {
Talk(words string)
}
type Cat struct {
name string
}
type Dog struct {
name string
}
func (c *Cat) Talk(words string) {
fmt.Printf("Cat " + c.name + " here: " + words + "\n")
}
func (d *Dog) Talk(words string) {
fmt.Printf("Dog " + d.name + " here: " + words + "\n")
}
func main() {
var t1, t2 Talker
t1 = &Cat{"Kit"}
t2 = &Dog{"Doug"}
t1.Talk("meow")
t2.Talk("woof")
}
答案 2 :(得分:2)
回答标题中的问题:
Go不使用类,但提供了许多相同的功能:
* message passing with methods * automatic message delegation via embedding * polymorphism via interfaces * namespacing via exports
解决你提供的代码,我将留给更多学问的Gopher
答案 3 :(得分:1)
Ad hoc多态性是静态类型语言的多态实现的一般方法。 Go中的多态性是ad hoc多态性,与Bjarne的Stroustrup定义非常接近:
多态性 - 为不同类型的实体提供单一接口。
Go interface
是专为多态实现而设计的强大工具。接口是一种类型抽象(方法集),它提供了一种指定对象行为的方法:如果某些东西可以做到这一点,那么它可以在这里使用。回到Straustrup的多态定义:如果实现接口,可以使用不同类型的对象作为公共接口的类型。
维基:
可以一般性地编写函数或数据类型,以便它可以相同地处理值而不依赖于它们的类型。
对于像Python或Ruby这样的动态类型语言,这种多态性更为常规,但Go也实现了它!为此,Go使用类型空接口interface{}
。
interface{}
来自Tour of Go:
指定零方法的接口类型称为空接口:
interface{}
空接口可以保存任何类型的值。每种类型至少实现零方法。处理未知类型值的代码使用空接口。例如,fmt.Print采用任意数量的
interface{}
类型的参数。
并且可以获得具有类型断言的特定类型的对象。
再次参观Tour:
类型断言提供对接口值的基本具体值的访问。
t := i.(T)
该语句声明接口值i保存具体类型T并将基础T值分配给变量t。
我们有静态鸭子类型的参数多态性。