一、基本介绍
在Go语言中,并没有像传统面向对象编程语言(Java、C++)中那样的类和继承的概念。Go语言采用了结构体和组合的方式来实现类似的功能。
在Go语言中,可以通过结构体嵌套来实现类似父类与子类的关系。当一个结构体嵌套了另一个结构体时,外层的结构体可以访问其嵌套结构体的字段和方法,这种方式被称为组合。Go语言中通过方法接受者的类型来决定方法的归属和继承关系。
示例代码:
package main
import "fmt"
// 父类
type Parent struct {
name string
}
// 父类的方法
func (p *Parent) SayHello() {
fmt.Println("Hello, I'm", p.name)
}
// 子类
type Child struct {
Parent // 嵌入父类
age int
}
func main() {
// 创建子类对象
c := &Child{
Parent: Parent{name: "John"},
age: 10,
}
// 调用父类的方法
c.SayHello()
// 访问父类的字段
fmt.Println("Parent name:", c.name)
// 访问子类的字段
fmt.Println("Child age:", c.age)
}
输出结果:
Hello, I'm John
Parent name: John
Child age: 10
二、接口的使用
Go语言可以在接口(interface)中声明一个方法但没有具体实现。接口在Go中是一种定义行为的类型,它允许你声明一个方法签名(方法名称、输出参数和返回值),而不需要实现这个方法。任何类型都可以实现这个接口,只要它提供了与接口声明中相同名称、相同签名的方法。
示例代码,父类的方法中使用了子类的方法:
package main
import "fmt"
// 定义一个接口,包含子类想要实现的方法
type BMethod interface {
B()
}
// 父类
type Parent struct{}
// 父类的方法,接受一个实现了BMethod接口的参数
func (p *Parent) A(b BMethod) {
fmt.Println("Parent's A method")
b.B() // 调用传入的B方法
}
// 子类
type Child struct {
*Parent // 嵌入父类,虽然在这个例子中嵌入并没有实际作用,因为Parent没有数据字段
}
// 子类实现BMethod接口的B方法
func (c *Child) B() {
fmt.Println("Child's B method")
}
func main() {
child := &Child{}
child.A(child) // 显式地将child作为参数传递给A方法
}
在Go语言中,一个结构体可以实现一个或多个接口。当结构体定义了与接口中声明的方法签名相匹配的方法时,我们就说该结构体实现了该接口。这并不需求显式地声明结构体实现了某个接口,而是通过实现接口中的方法来隐式地完成。
示例代码:
package main
import "fmt"
// 定义一个接口
type Shape interface {
Area() float64
}
// 定义一个结构体
type Rectangle struct {
width float64
height float64
}
// 为Rectangle结构体实现Area方法
func (r Rectangle) Area() float64 {
return r.width * r.height
}
func main() {
// 创建一个Rectangle对象
rect := Rectangle{width: 10, height: 5}
// 调用Area方法
fmt.Println("Rectangle area:", rect.Area())
// 隐式地将Rectangle对象赋值给Shape接口变量
var s Shape
s = rect
// 通过接口变量调用Area方法
fmt.Println("Shape area:", s.Area())
}