在Go语言中没有了class 类关键字,但是这并不代表Go语言不能使用面向对象编程,在Go语言中使用了struct关键和interface 关键字来定义对象和方法接口。具体如下:
面向对象
Go中使用struct来定义类,假如我们需要定义一个person类,其中包含姓名、年龄等信息。我们可以使用struct关键字来定义(这个和c语言中的struct一样,只不过Go的struct支持的特性更多)。
package main import ( "fmt" ) type person struct { # 定义结构体包含信息 name string age int } func main() { s1 := person{"aa", 22} # 初始化信息 fmt.Println(s1) }
类的继承,现在假如在添加一个学生类(包含姓名、年龄、学校、班级号),我们可以使用使用类似于类中的继承的概念来使用刚才定义的person结构体。
package main import ( "fmt" ) type Person struct { name string age int } type student struct { Person # 匿名字段, 相当于继承了person的信息 school string class_num int } func main() { p1 := Person{"aa", 22} fmt.Println(p1) s1 := student{ Person{"aa", 12}, "school", 12} # 初始化 fmt.Println(s1) }
在Go语言中多继承也是可以的,就是用在需要继承的结构体中将继承的结构体添加进就完成了。例如我们定义两个基类表示信息和父母类,子类继承这两个类。
package main
import (
"fmt"
)
type Person struct {
name string
age int
}
type partent struct {
fater string
mother string
}
type SpeciStudent struct {
Person
partent
info string
}
func main() {
ss := SpeciStudent{Person{"bb", 35}, partent{"bb_father", "bb_mother"}, "bb is good student"}
fmt.Println(ss)}
既然是类,则自然有类方法,在Go语言中方法的定义为
func (变量 结构体名) 方法名() { # 定义方法
方法内容
}
package main
import (
"fmt"
)
type Person struct {
name string
age int
}
func (p Person) printInfo() {
fmt.Println(p.name, p.age)
}
func main() {
p1 := Person{"aa", 22}
p1.printInfo()
}
在面向对象中,子类可以继承父类的方法,父类不能使用子类特有的方法。在Go语言也同样遵守这个规则。
package main import ( "fmt" ) type Person struct { name string age int } func (p *Person) printInfo() { fmt.Println(p.name, p.age) } type student struct { Person school string class_num int } func(s student) printinfo(){ fmt.Println(s.name, s.age, s.class_num,s.school) } func main() { p1 := Person{"aa", 22} p1.printInfo() s1 := student{ Person{"aa", 12}, "school", 12} # 初始化子类 s1.printInfo() # 调用父类的方法 s1.printinfo() # 调用自己的方法 }
在面向对象编程中经常使用接口, 接口好比一种模版,这个模版定义了对象必须实现的方法,其目的就是让这些方法可以作为接口实例被引用。接口不能被实例化。类可以实现多个接口并且通过这些实现的接口被索引。接口变量只能索引实现该接口的类的实例。
/ * 接口定义
type 接口名 interface {
方法() 返回类型
}
注意: 接口不能实例化、类中只有实现了接口的全部方法才能赋值给接口变量(否则会报错)、
*/
package main import ( "fmt" ) type Personer interface { // 定义接口 printInfo() } type Person struct { name string age int } func (p *Person) printInfo() { fmt.Println(p.name, p.age) } func main() { var interp Personer p1 := Person{"aa", 22} interp = &p1 interp.printInfo() }
多态的实现,在面向对象中如果传入的类型不同,函数执行的结果也不同。这里我们可以利用接口来实现多态。
package main
import (
"fmt"
)
type Personer interface {
printInfo()
}
type Person struct {
name string
age int
}
func (p *Person) printInfo() {
fmt.Println(p.name, p.age)
}
type student struct {
Person
school string
class_num int
}
func(s student) printInfo(){
fmt.Println(s.name, s.age, s.class_num,s.school)
}
func printinfo(p Personer) { // 定义函数,其中参数为接口类型,意味着如果传入参数的不同,我们调用的方法也将不同
p.printInfo()
}
func main() {
p1 := Person{"aa", 22}
printinfo(&p1)
s1 := student{Person{"bb", 24}, "bb_school", 13 }
printinfo(&s1)
}
关于接口的继承,就像和对象的继承是一样的,通过匿名字段来紧凑型设置,注意的是父接口不能转换成子接口, 但是子接口可以转换成父接口
type Personer interface { printInfo() } type Personer2 interface { // 这时 person2中拥有person中的方法, Personer setInfo() }
最后还有一个空接口类型,空接口就是里面花括号里面什么都没有,在Go语言中空接口变量可以接收任意类型的数据,包括整数、浮点数、函数、字符串等等。另外可以看一一下fmt.Println()函数,你会看到参数就是一个接口类型。
package main import "fmt" func main() { type i interface {} // 空接口类型 var L1 i // 定义空接口变量 L1 = 10 // 赋值 fmt.Println(L1) L1 = 1.2 fmt.Println(L1) L1 = "aaaa" fmt.Println(L1) }