我正在深入研究Go架构,并且在多态性方面遇到问题。我简化了问题,并为此示例创建了新数据,以使我的问题更容易理解。
我有这样的结构:
type Animal interface {
speak() string
}
type Cat struct {
Name string
}
type Dog struct {
Race string
}
我希望这些结构体实现该接口,我这样进行:
func (c Cat) speak() string {
return "Miaw!"
}
func (d Dog) speak() string {
return "Guau!"
}
func speak(a Animal) string {
return a.speak()
}
func speaks(a []Animal) string {
str := ""
for i := 0; i < len(a); i++ {
str += a[i].speak()
}
return str
}
所以我创建的是:
方法speak
接收到Animal
并执行给定结构(Animal
,即Cat
或Dog
的方法,以及方法{{ 1}}接收speaks
的一个切片,并执行该切片的每个索引(Animal
,即Animal
或Cat
)中给出的结构的方法。 / p>
为了测试这些方法,我实现了此功能:
Dog
我上传了编译器给我的错误:
有人可以向我解释为什么我可以在仅接收一个元素的函数中玩polimorfish吗,为什么不能在接收该元素的切片的函数中玩polimorfish?
我真的需要找到该问题的解决方案以在我的应用程序的不同部分中实现它,我也不知道如何解决该问题,也不知道如何实现一个实用且可扩展的解决方案(实际应用中的切片将包含大量元素。
我发现与这个答案相关的信息对于理解更多我的问题很有帮助,但仍然我不明白问题是什么或解决方法: Answer1 Answer2 Answer3
答案 0 :(得分:1)
Go无法键入强制转换数组。您需要手动创建目标类型的新数组,然后使用for循环将类型转换为源数组的每个元素并将结果放入目标数组。
原因:go不会从您的内存分配中隐藏,这就是为什么您需要手动创建新内容并感觉到它的原因。
答案 1 :(得分:0)
固定版本,位于Play
正如其他人提到的那样,Go中没有自动强制类型转换。 而且[] Cat与[] Animal完全不同。
您真正需要做的就是创建要传递给speaks
方法的类型的切片。
因此,请更改:
arrayCats := []Cat{cat1, cat2, cat3}
到
arrayCats := []Animal{cat1, cat2, cat3}
它工作正常。
如果您习惯使用Java之类的语言,那么它们会以一种完全不同的方式进行处理,因为Java将所有事物都视为Object
。因此,当他们添加泛型时,这是一个简单的编译时技巧,集合实际上只是Object
的列表,并且编译器在提取点插入了强制类型转换。
像int
这样的东西不是Java中的对象,这就是为什么您不能创建List<int>
的原因,因为这样List<Object>
的转换技巧将不起作用。因为int
不是Object
的子类。
在使用过程中,没有像struct这样的通用基类型,因此没有真正的方法可以像Java一样进行转换。
正如其他人提到的那样,go如何管理内存也有一些特定功能,这些功能使自动转换等操作无法以通用方式工作(即:一片int64与一片int32是不同的内存占用空间,因此没有分配就无法投放)。
go团队表示,他们正在寻找以某种形式添加泛型的方法,这可能会使这种事情更容易编写。但这将带来隐形运行时或编译时复杂性(或两者都有)的代价。
今天,由于它不是自动的,因此您必须编写代码来进行转换。 不利之处在于您编写更多代码。而且它的好处很明显,就是系统中正在发生什么。