Golang Go语言中子类对象赋值给父类的疑惑
package main
import “fmt”
type A struct {
animal Animal
}
type Animal struct {
Name string
}
func (a Animal) Move() {
fmt.Printf("%s is moving\n", a.Name)
}
// 现在我想扩展一下 animal 的 Move 方法
type Dog struct {
Animal // 嵌入结构体
Breed string
}
func (d Dog) Move() {
fmt.Printf(“Dog is Move”)
}
func main() {
dog := Dog{
Animal: Animal{Name: “Buddy”},
Breed: “Golden Retriever”,
}
// 报错
a.animal = dog
}
实际工作中还是有这样的场景的,某个 class/struct 里面引用了一个外部的 class/struct 。我想对他调用的某个函数进行扩展一下,Java 里面,我只要继承这个外部的类,然后 override 一下我需要改写的方法,然后再改写一下赋值语句就可以。但是 golang 中好像不行,必须把类型也改了才能赋值。
当然了,如果这个变量类型是个 interface 的话,倒是可以的,但是现实情况中遇到的就是个 struct 。
Golang Go语言中子类对象赋值给父类的疑惑
更多关于Golang Go语言中子类对象赋值给父类的疑惑的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html
了解一下 go 中interface
的概念go<br>package main<br><br>import "fmt"<br><br>// 定义一个 Animal 接口<br>type AnimalInterface interface {<br> Move()<br>}<br><br>// 定义 Animal 结构体<br>type Animal struct {<br> Name string<br>}<br><br>func (a Animal) Move() {<br> fmt.Printf("%s is moving\n", <a target="_blank" href="http://a.Name" rel="nofollow noopener">a.Name</a>)<br>}<br><br>// 定义 Dog 结构体,嵌入 Animal<br>type Dog struct {<br> Animal // 这里嵌入了 Animal<br> Breed string<br>}<br><br>// Dog 实现 AnimalInterface 接口<br>func (d Dog) Move() {<br> fmt.Printf("Dog %s is moving\n", <a target="_blank" href="http://d.Name" rel="nofollow noopener">d.Name</a>)<br>}<br><br>type A struct {<br> animal AnimalInterface<br>}<br><br>func main() {<br> dog := Dog{<br> Animal: Animal{Name: "Buddy"},<br> Breed: "Golden Retriever",<br> }<br> <br> // 赋值给 A 中的 animal 字段<br> a := A{animal: dog}<br> <br> // 调用 Move 方法<br> a.animal.Move() // 输出: Dog Buddy is moving<br>}<br>
更多关于Golang Go语言中子类对象赋值给父类的疑惑的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html
可以使用接口来定义行为,然后让结构体实现该接口. golang 的思想和 java 不一样
首先,Go 里没有类…
<br>package main<br><br>import "fmt"<br><br>type Animal struct {<br> Name string<br>}<br><br>func (a Animal) Move() {<br> fmt.Printf("%s is moving\n", <a target="_blank" href="http://a.Name" rel="nofollow noopener">a.Name</a>)<br>}<br><br>// 现在我想扩展一下 animal 的 Move 方法<br><br>type Dog struct {<br> *Animal // 嵌入结构体<br> Breed string<br>}<br><br>func (d Dog) Move() {<br> fmt.Printf("Dog is Move")<br>}<br><br>func main() {<br> dog := Dog{<br> Animal: &Animal{Name: "Buddy"},<br> Breed: "Golden Retriever",<br> }<br> // 不会报错<br> dog.Move()<br>}<br><br>
理解错了,还要赋值给一个明确类型的结构体变量,那必然要用 interface 了。
go 里没有类,更没有封装,没有继承,没有子类父类等等所有 jvav 里的糟粕
你要做的只是定义个函数然后调用就好了。struct 只是个数据结构不是 class
Go 没有类只有数据结构 没有继承只有组合
组合优于继承 但 go 的组合更好
在 java 里除了变量可视或称封装以外还有继承阻挡你动态的应用自己或别人写的东西 go 里就变量可视最麻烦 因应业务将架构调整成适合的样子 go 方便很多 动态性差的东西解决需求麻烦非常多
拉踩 java 能体现优越感🤡
确实滥用继承而非继承本身才是问题 关键。但问题是,Java 设计上就强迫开发者必须滥用继承,尤其是加入 interface 实现之前。
问题还是在与 golang 没有真正的"继承"概念,也就没有针对父子类的多态,因此不能方法重写
问题是不管开源项目还是公司项目滥用的是一堆阿
谁也没强迫 Javaer 去滥用继承啊。一个人的水平不行怎么能怪语言设计的不好呢?虽然 Java 语言也确实有不少槽点,但继承真的不是。继承就是封装的一种语言级别的体现而已。
其实 Golang 的 Embedding (嵌入) 也很灵活,因为嵌入不光能够嵌入 struct ,还能嵌入 interface 。
经典的实现是标准库 context ,比如实现 context.WithCancel 的关键结构体 cancelCtx ,就是嵌入了接口 Context ,当 cancelCtx 初始化时,会把 parent 塞给 cancelCtx.Context ,关键在于由于 cancelCtx.Context 是个接口,所以你可以把任意实现了 Context 接口的类型作为 parent 塞给 cancelCtx ,以此实现一种“继承”。
cancelCtx 源码:
https://github.com/golang/go/blob/76f3e0ac8d094b2bc5f8a3fb8a19d1d17a07fe2c/src/context/context.go#L423
这就是为什么不同的 context 底层结构体( cancelCtx 、timerCtx 、valueCtx……)可以通过 WithCancel 、WithDeadline 、WithValue 等标准库方法组成一个灵活的“context 链”, 还能够基于拼接顺序 “override” 各自的实现方法,第一次看源码的时候觉得还是挺奇妙的。
所以当你有扩展行为实现的需求的时候,在 Go 确实要首先考虑用接口
现在生态都是过度设计和滥用的你要怎么避? 继承本身的侷限性也不如组合灵活
Java 没有内建元编程支持,没有 mixin 语法,class 不支持动态代理,在早期也没有 interface 默认实现。 不用继承,你打算怎么实现代码复用,一个个方法手写 adapter 吗?
在Go语言中,并没有传统面向对象编程中的“子类”和“父类”的概念,而是使用了结构体(struct)和接口(interface)来实现类似的功能。你提到的“子类对象赋值给父类”,在Go中通常是通过接口来实现的。
在Go中,一个结构体可以实现一个或多个接口,而接口定义了对象的行为。当你将一个结构体实例赋值给一个接口类型时,只要该结构体实现了接口中的所有方法,这个赋值就是合法的。这实际上就实现了类似于“子类对象赋值给父类”的效果,但这里的“父类”是一个接口。
例如:
type Animal interface {
Speak() string
}
type Dog struct{}
func (d Dog) Speak() string {
return "Woof!"
}
func main() {
var a Animal
d := Dog{}
a = d // 将Dog实例赋值给Animal接口
fmt.Println(a.Speak()) // 输出: Woof!
}
在这个例子中,Dog
结构体实现了Animal
接口,因此Dog
的实例可以赋值给Animal
类型的变量。这样,你就可以通过接口来引用实现了该接口的结构体实例,从而实现了类似面向对象编程中的多态性。
总的来说,Go语言通过接口和结构体提供了一种灵活且强大的方式来模拟面向对象编程中的继承和多态性。