我正在努力巩固Go提供的遗传概念(可能是“组合”而不是纯粹的遗传)。但是,我无法理解为什么我不能使用“父”类型作为func
参数来生成一个作用于参数的泛型函数。
package main
import "log"
type Animal struct {
Colour string
Name string
}
type Dog struct {
Animal
}
func PrintColour(a *Animal) {
log.Printf("%s\n", a.Colour)
}
func main () {
a := new (Animal)
a.Colour = "Void"
d := new (Dog)
d.Colour = "Black"
PrintColour(a)
PrintColour(d)
}
假设我的理解不正确,我怎样才能在Go中实现我想要的东西?
修改 注意:
我不想将行为附加到struct
我想将指针类型保留为方法参数,因为我在宠物项目上单独工作,这需要我操纵传入的结构然后再对其进行操作。
实际上我的Dog
结构将有其他字段/成员;希望这不会使水进一步混乱
答案 0 :(得分:13)
到目前为止,我喜欢这里的答案,我想添加一个允许您使用接口传递的接口上进行静态类型检查的内容:
package main
import (
"fmt"
)
type Animalizer interface {
GetColour() string
}
type Animal struct {
Colour string
Name string
}
type Dog struct {
Animal
}
func (a *Animal) GetColour() string {
return a.Colour
}
func PrintColour(a Animalizer) {
fmt.Print(a.GetColour())
}
func main() {
a := new(Animal)
a.Colour = "Void"
d := new(Dog)
d.Colour = "Black"
PrintColour(a)
PrintColour(d)
}
可以向Dog
添加更多字段。与Uriel的答案不同的是,如果传入实现PrintColour
的结构之外的其他内容,则在编译时对Animalizer
的调用将失败。
此外,您不必使用typeswitch,因为编译器知道Animalizer
正在实施GetColour
。
最后,行为(打印)与结构分开,GetColour
只返回颜色。
答案 1 :(得分:4)
如果您在PrintColour
类型上声明Animal
方法,那么当您在Animal
中加入Dog
时,该方法将被“继承”。
这在Go世界中被称为“嵌入”。有关详细信息,请参阅The "Embedding" section of Effective Go。
尝试类似:
package main
import "log"
type Animal struct {
Colour string
Name string
}
type Dog struct {
Animal
}
func (a *Animal) PrintColour() {
log.Printf("%s\n", a.Colour)
}
func main () {
a := new (Animal)
a.Colour = "Void"
d := new (Dog)
d.Colour = "Black"
a.PrintColour()
d.PrintColour()
}
产地:
2009/11/10 23:00:00无效
2009/11/10 23:00:00黑色
答案 2 :(得分:3)
您可以使用interface{}
package main
import ("fmt"
"reflect")
type Animal struct {
Colour string
Name string
}
type Dog struct {
Animal
}
func PrintColour(a interface{}) {
switch a.(type){
case *Dog:
fmt.Printf("Dog %s\n", a.(*Dog).Colour)
case *Animal:
fmt.Printf("Aimal %s\n", a.(*Animal).Colour)
default:
fmt.Printf("hmm %s\n", reflect.TypeOf(a))
}
}
func main () {
a := new (Animal)
a.Colour = "Void"
d := new (Dog)
d.Colour = "Black"
PrintColour(a)
PrintColour(d)
}
答案 3 :(得分:1)
仍然可以使用typename:
显式访问嵌入式(匿名)字段package main
import "log"
type Animal struct {
Colour string
Name string
}
type Dog struct {
Animal
}
func PrintColour(a *Animal) {
log.Printf("%s\n", a.Colour)
}
func main() {
a := new(Animal)
a.Colour = "Void"
PrintColour(a)
d := new(Dog)
d.Colour = "Black"
// you can access the underlying "Animal" through "d.Animal"
PrintColour(&d.Animal)
}
In the reference:第二个代码块之后的句子解释了如何声明“匿名”字段,并声明:
非限定类型名称充当字段名称。
答案 4 :(得分:1)
我的例子可能不太好,但你可以这样做你想做的事情:
http://play.golang.org/p/JoAlOvJthr
基本上使用一个接口来定义您希望为所有类型和嵌入类型公开的外部世界的通用功能。
(我的例子可能不是最好但是有效)