golang中接口、继承

本文介绍了Go语言中的接口概念,如何定义和实现接口,包括一个具体的Person接口示例。同时,阐述了空接口EmptyInterface的特性,指出任何类型都是空接口的实例。此外,讨论了接口对象的类型转换方法,并通过示例展示了如何进行类型判断。最后,提到了Go语言中通过匿名结构体字段模拟继承的方式。

在面向对象编程中(OOP)接口定义对象的一系列行为,具体对象实现接口的行为。在golang中,接口就是一组方法签名,如果某个类型实现了该接口的全部方法,这个类型就实现了该接口,是该接口的实现。
在golang中接口定义示例如下:

type MyInterface interface {
	SayHello()
	GetAge() int
}

这样我们就定义了一个MyInterface类型的接口,如果我们想要实现这个接口,只要一个类型实现MyInterface的两个方法:SayHelloGetAge:

type Person struct {
	age int
	name string
}

func (p Person)SayHello(){
	fmt.Println("hello ",p.name)
}

func (p Person)GetAge() int{
	return p.age
}

这样Person类就实现了MyInterface接口,接下来可以按照如下方式使用:

	var myInterFace MyInterface
	myInterFace = Person{age:20,name:"Leo"}
	myInterFace.SayHello()
	myInterFace.GetAge()
空接口

golang中的空接口,类似于java中的Object超级父类。golang中空皆苦没有任何方法,任意类型都是空接口的实现,空接口定义如下:

type EmptyInterface interface {
	
}

这里EmptyInterface就是一个空接口,这时候,上面的Person也是该接口的实现:

	var empty EmptyInterface
	empty = Person{age:20,name:"empty"}
接口对象类型转换

如果我们声明了一个接口类型,但是实际指向是一个对象,我们可以通过如下几种方式进行接口和对象类型的转换:
1.

	if realType,ok := empty.(Person); ok{
		fmt.Println("type is Person ",realType)
	} else if realType,ok := empty.(Animal) ;ok{
		fmt.Println("type is Animal",realType)
	}

这种方式可以借助if else进行多个类型的判断
2.

	switch realType2 := empty.(type) {
	case Person :
		fmt.Println("type is Person",realType2)
	case Animal :
		fmt.Println("type is Animal",realType2)
	}
继承

在golang中,采用匿名结构体字段来模拟继承关系。


type Person struct {
	name string
	age int
	sex string
}
func (Person) SayHello(){
	fmt.Println("this is from Person")
}

type Student struct {
	Person
	school string
}


func main() {
	stu := Student{school:"middle"}
	stu.name = "leo"
	stu.age = 30
	fmt.Print(stu.name)

	stu.SayHello()
}

这个时候,可以说Student是继承自Person.

需要注意的是,结构体嵌套时,可能存在相同的成员名,成员重名可能导致成员名冲突:

type A struct {
	a int
	b string
}
type B struct {
	a int
	b string
}

type C struct {
	A
	B
}


	c := C{}
	c.A.a = 1
	c.A.b = "a"
	c.B.a = 2
	c.B.b = "b"
	
	// 这里会提示a名字冲突
	fmt.Println(c.a)

### Golang 中的继承概念与实现 在 Go 语言中,并不存在传统意义上的类(class),因此也没有经典面向对象编程中的继承机制。然而,Go 提供了一种称为 **组合(composition)** 的特性来替代继承[^1]。 #### 组合式继承 当一个结构体包含了另一个或多个匿名字段(这些字段本身也是结构体),这就形成了所谓的“组合”。这种设计模式允许外部结构体直接访问内部匿名结构体的方法和属性,从而模拟了多继承的效果[^3]。 例如,在给定的例子中: ```go type Goods struct { Name string Price float64 } type Book struct { Goods // 匿名字段, 表示Book拥有Goods的所有属性 Writer string } ``` 这里 `Book` 类型不仅具有自己的 `Writer` 属性,同时也具备来自 `Goods` 的所有成员变量(`Name`, `Price`)以及任何可能定义在其上的方法。这便是通过组合实现了类似于其他语言里的单重甚至多重继承的功能[^4]。 对于更复杂的场景,可以进一步嵌入更多层次或者不同类型的结构体以构建复杂的数据模型。需要注意的是,虽然这种方式看起来像是继承关系,但实际上它只是简单地把各个部分组装在一起而已;每个组件仍然是独立存在的实体[^2]。 #### 接口与多态 除了上述提到的基于结构体的组合之外,Go 还利用接口(interface)支持多态行为。只要某个类型满足特定接口的要求——即实现了该接口所规定的一组函数签名,则此类型就可以被当作那个接口类型处理。这样就达到了动态绑定的目的,而无需依赖于传统的继承体系。 ```go // 定义一个简单的接口 type Speaker interface { Speak() string } // Dog 结构体及其Speak方法实现 type Dog struct{} func (d *Dog) Speak() string { return "Woof!" } // Person 结构体也实现了同样的接口 type Person struct{} func (p *Person) Speak() string { return "Hello!" } ``` 在这个例子中,无论是 `*Dog` 或者 `*Person` 都能作为 `Speaker` 使用,因为它们都提供了符合预期的行为实现。这是另一种形式上接近继承的概念,但在实际操作层面更加灵活且易于维护。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值