GO 语言接口与结构体 - interface & struct
source link: https://studygolang.com/articles/22424?fr=sidebar
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
GO 语言接口与结构体 - interface & struct
坚果jimbowhy · 2019-08-02 22:32:40 · 4826 次点击 · 预计阅读时间 3 分钟 · 大约8小时之前 开始浏览interface & struct 接口与结构体
以继承为特点的 OOP 只是编程世界的一种抽象方式,在 Golang 的世界里没有继承,只有组合和接口,并且是松散的接口结构,不强制声明实现接口,这看起来更符合 Java 之父 Gosling 的设想。
If it looks like a duck, swims like a duck, and quacks like a duck, then it probably is a duck.
翻译过来就是:如果某个东西长得像鸭子,像鸭子一样游泳,像鸭子一样嘎嘎叫,那它就可以被看成是一只鸭子。
单一继承关系解决了 is-a 也就是定义问题,因此可以把子类当做父类来对待。但对于父类不同但又具有某些共同行为的数据,单一继承就不能解决了,C++ 采取了多继承这种复杂的方式。
GO 采取更贴近现实世界的网状结构,不同于继承,GO 语言的接口是松散的结构,它不和定义绑定。从这一点上来说,Duck Type 相比传统的 extends 是更加松耦合的方式,可以同时从多个维度对数据进行抽象,找出它们的共同点,使用同一套逻辑来处理。
接口使用例子,定义MyString
类型与string
一样,再实现 VolwelsFInder
接口的方法,使用时只需要实例化对象并赋予接口即可以访问接口规范的方法,rune
是基本数据类型格式 Unicode 字符:
package main
import (
"fmt"
)
//定义interface
type VowelsFinder interface {
FindVowels() []rune
}
type MyString string
// 实现接口
func (ms MyString) FindVowels() []rune {
var vowels []rune
for _, rune := range ms {
if rune == 'a' || rune == 'e' || rune == 'i' || rune == 'o' || rune == 'u' {
vowels = append(vowels, rune)
}
}
return vowels
}
func main() {
name := MyString("Sam Anderson") // 类型转换
var v VowelsFinder // 定义一个接口类型的变量
v = name
fmt.Printf("Vowels are %c", v.FindVowels())
}
所有类型都实现了空接口 Empty Interface 表示为interface {}
,因此可以对任何类型进行类型断言 Type Assertions,但要先转换成接口在进行类型断言检查。类型断言检查是对接口类型进行的动态类型检查,语法格式 x.(T)
,T 就是断言类型,通过断言检查就可以从操作数中得到具体的类型数据。如下面尝试将变量类型 s 转换成 string,先将 s 转换成空接口interface{}(v)
,再进行 .(string)
断言:
val, ok := interface{}(v).(string)
GO 语言的结构体 struct 是组合非继承,不像其它 OOP 语言那样通过继承机制实现类结构的扩展。
下面例程中,Being 是最基础的结构体,Human 组合了 Being,而 Student 又组合了 Human。 但是通过 Human.Eat() 方法调用 Drink() 只能是 Human.Drink()。如果 Student 也实现了 Eat 方法并调用 Dranking(),则会调用自己的 Student.Dranking()。
对 s 分别进行了 Human、Student 类型断言,输出结果可以看到,s 断言 Human 是不成功的,因为它是 Student 类型。断言 IHuman 接口也是成功的,因为 Student 结构实现了 IHuman 接口的所以方法。也就是说看起来叫起来都像鸭子的东西,那就可以认为它是鸭子
package main
import "fmt"
func main(){
var h Human
s := Student{Grade: 1, Human: Human{Name: "Jason", Age: 12, Being: Being{IsLive: true}}}
fmt.Println("student:", s)
fmt.Println("student ", s.Name, " is alive:", s.IsLive )
// h = s // cannot use s (type Student) as type Human in assignment
fmt.Println(h)
// Heal(s) // cannot use s (type Student) as type Being in argument to Heal
Heal(s.Human.Being) // true
s.Drink() // student drinking...
s.Eat() // human eating... & human drinking...
human, b := interface{}(s).(Human) // false s is Student but Human
fmt.Println(human, b)
student, b := interface{}(s).(Student)
fmt.Println(student, b)
ihuman, b := interface{}(s).(IHuman)
fmt.Println(ihuman, b)
}
type Being struct {
IsLive bool
}
type Human struct {
Being
Name string
Age int
}
func (h Human) Eat(){
fmt.Println("human eating...")
h.Drink()
}
func (h Human) Drink(){
fmt.Println("human drinking...")
}
type Student struct {
Human
Grade int
}
func (s Student) Drink(){
fmt.Println("student drinking...")
}
func Heal(b Being){
fmt.Println(b.IsLive)
}
type IHuman interface {
Eat()
Drink()
}
有疑问加站长微信联系(非本文作者)
入群交流(和以上内容无关):加入Go大咖交流群,或添加微信:liuxiaoyan-s 备注:入群;或加QQ群:701969077
Recommend
About Joyk
Aggregate valuable and interesting links.
Joyk means Joy of geeK