Go语言没有对象的概念,没有生产对象的关键字,但是go语言的特性却可以用原生语法来模拟面向对象的特性。
面向对象的特征是:继承,一种联结类的层次模型;封装,把过程和数据包围起来,对数据的访问只能通过已定义的api;多态,父类中定义的属性或方法被子类继承之后,可以具有不同的数据类型或表现出不同的行为。
抽象
面向对象的抽象性就是把现实世界中的某一类东西,提取出来,用程序代码表示,抽象出来的一般叫做类或者接口。
/**
动物类
*/
type Animals struct {
name string //动物名称
eat string //动物食性
}
/**
动物接口
*/
type AnimalsAbstractMethod interface{
showColor() string //动物颜色
showteech() string //动物牙齿
showlocation() string //生活地区
}
在go语言中结构体是属性的集合,结构体只能有属性。接口是方法的集合,接口只能是抽象方法(没有方法体)。
继承
子类继承父类的属性和行为,并根据自己的需求来扩展行为 。
go语言没有class的概念,也就没有extend的用法。要实现模拟类的行为,就必须要有类的方法和属性,在go中结构体可以定义属性,方法可以指向结构体,接口可以定义抽象方法,因此也可以实现继承。
类行为
在go中继承就是结构体的嵌套,方法直接重写方法体即可。
//继承模拟
/*
结构体构造属性
*/
type Animals struct {
name string //动物名称
eat string //动物食性
}
/*
方法构造类方法
*/
func (animals Animals) toString() string {
return "Animals{" + animals.name + "," + animals.eat + "}"
}
/*
结构体嵌套模拟继承
*/
type Herbivore struct {
animals Animals //父类嵌套在类中提供父类的属性
teech string
}
/*
重写方法
*/
func (berbivore Herbivore) toString() string {
return "Herbivore{name=" + berbivore.animals.name + ",eat=" + berbivore.animals.eat + "}"
}
/*
实例化
*/
h1 := Herbivore{
animals: Animals{
"狗子",
"杂食动物",
},
teech: "尖锐的牙齿",
}
fmt.Println(h1)
fmt.Println(h1.toString())
接口行为
go中接口是抽象函数的集合,go在先类的概念是和其他语言是不一样的,是一种新的概念。用方法重写接口的抽象方法,指向继承类即可。
/*
动物接口
*/
type animalsBehavior interface {
showColor() string //动物颜色
showlocation() string //生活地区
}
/*
实现接口的方法并指向结构体
*/
func (berbivore Herbivore) showColor() {
fmt.Println("打印动物颜色")
}
func (berbivore Herbivore) showlocation() {
fmt.Println("打印动物生活区域")
}
重写的方法指向某个结构体,则结构体的实例就可以使用重写的抽象方法。
h1 := Herbivore{
animals: Animals{
"狗子",
"杂食动物",
},
teech: "尖锐的牙齿",
}
fmt.Println(h1)
fmt.Println(h1.toString())
//使用抽象方法
h1.showColor()
h1.showlocation()
封装
封装是面向对象的特征之一,是对象和类概念的主要特性。封装就是把过程和数据包围起来,对数据的访问只能通过已定义的API。
Go语言中函数是基本单位,在go语言中通过变量首字母的大小写控制访问权限,因此使用Go实现面向对象的功能是需要借助该特性。
Go语言的访问权限的控制没有Java那么严格,首字母的大小写只限制了包以外的访问权限,在包内都可以访问到。
如下所示定义四个目录:
Animals是父类,Herbivore是子类,main是主类,Test是测试类。
- Animals报下go文件内容
package Animals
/**
动物类
*/
type Animals struct {
Name string //动物名称
Eat string //动物食性
}
//方法指向动物结构体
func (animals Animals) makeAnimals(name string, eat string) {
animals.Name = name
animals.Eat = eat
}
func (animals Animals) toString() string {
return "Animals{" + animals.Name + "," + animals.Eat + "}"
}
Animals结构体属性首字母大写,才能在其他目录访问到,编写了两个方法指向结构体。方法名首字母是小写的也就意味者外部包无法访问。
在主类中引入包,并调用
package main
import (
"fmt"
"unit4/src/class/Animals"
// "unit4/src/class/Herbivore"
)
func main() {
var a1 = Animals.Animals{
Name: "小狗",
Eat: "杂食动物",
}
fmt.Println(a1)
}
没有小写字母的方法,因此在外部包不能调用。
当将员包改为大写时,如下:
//方法指向动物结构体
func (animals Animals) MakeAnimals(name string, eat string) {
animals.Name = name
animals.Eat = eat
}
func (animals Animals) ToString() string {
return "Animals{" + animals.Name + "," + animals.Eat + "}"
}
就可以调用方法了,
通过首字母的大小写完成了结构体方法和属性私有性的限定。
多态
父类中定义的属性或方法被子类继承之后,可以具有不同的数据类型或表现出不同的行为。
在上述的案例中,再编写一个Animals包中定义一个接口,内容如下:
type Animals struct {
Name string //动物名称
Eat string //动物食性
}
type animalsBehavior interface {
ShowColor() string
ShowHeight() float32
}
func (animals Animals) ShowColor() {
fmt.Println("animals color")
}
func (animals Animals) ShowHeight() {
fmt.Println("animals height")
}
在其继承类中,重写父类的方法
type Herbivore struct {
Animals Animals.Animals
Location string
}
/*
重写父类方法
*/
func (animals Herbivore) ShowColor() {
fmt.Println("颜色时黄色")
}
func (animals Herbivore) ShowHeight() {
fmt.Println("体重30公斤")
}
在主类中生产实例并调用方法,
h1 := Herbivore.Herbivore{
Animals: Animals.Animals{
Name: "小狗",
Eat: "杂食动物",
},
Location: "主人家",
}
fmt.Println(h1)
h1.ShowColor()
h1.ShowHeight()
h2 := Herbivore.Herbivore{
Animals: Animals.Animals{
Name: "小2",
Eat: "杂食动物2",
},
Location: "主人家2",
}
fmt.Println(h2)
h2.ShowColor()
h2.ShowHeight()
通过不同的实例化和方法的重写使对象的不同实例表现不同的行为。
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/156156.html