目录
1.Go语言中的面向对象
/*
1.概念:
go不是一个面向对象的语言,可以使用结构体和接口模拟面向对象;面向对象的思想就是万物皆对象,
不一步步的自己去做一些事情,而是根据相同事物的特性抽取出一个类, 通过类创建一个对象,由对象去完
成这个功能。如:洗衣服不再一步步的自己洗,而是买个全自动洗衣机,让洗衣机去洗。
2.面向对象三大特性
2.1:封装:
对象包括了属性和行为;Go语言通过结构体和接口实现封装,结构体封装了字段(属性),接口封
装了方法(行为)。
2.2:继承:
子类通过在结构体中定义父类的匿名字段实现封装;子类继承父类后就继承了父类定义的所有
字段和方法;可以通过子类对象名.父类的属性或方法直接使用父类定义的字段和属性;结构体和接
口都是可以多继承的。
2.3:多态:
多态是指一个事物拥有多种形态,如动物包含了猫、狗、羊....,包括了向上转型和向下转型,
多态默认就是向上转型(父类引用指向子类对象),如果向下转型(父类对象强转为子类对象),需要进行
断言,否则可能出现错误。
*/
2.继承: 可以直接通过子类对象名.父类字段调用父类属性
//定义父类结构体
type Person struct {
name string
age int
}
//定义子类结构体
type Student struct {
Person // 通过定义父类的匿名字段实现继承
school string
}
func main() {
//1.定义单独的父类对象
person := Person{
name: "张三",
age: 23,
}
fmt.Println(person)
//2.定义子类对象
student := Student{
Person{
name: "李四",
age: 23,
},
"山东大学",
}
fmt.Println(student)
fmt.Println(student.name)//注意: 继承之后可以直接通过子类对象名.父类字段调用父类属性
}
3.聚合:不能直接通过子类对象名.父类字段调用父类属性
type Address struct {
city string
province string
}
//不使用匿名字段叫聚合,不能使用子类对象名.父类属性进行使用
type Person struct {
name string
age int
address Address
}
func main() {
person := Person{
name: "张三",
age: 23,
address: Address{
city: "菏泽市",
province: "山东省",
},
}
fmt.Println(person)
//fmt.Println(person.city)//不能使用
fmt.Println(person.address.province)
}
4.方法
/*
在Go语言只能够函数和方法不是一个东西;函数是一段独立功能的代码,方法是指定调用者的一段独立功能的代码,不同调用者之间方法名可以重复。
格式:
func (结构体名称 结构体) 方法名(){
//方法体
}
*/
//定义结构体
type Dog struct {
name string
age int
}
type Cat struct {
name string
age int
}
// 定义方法
func (dog Dog) eat() {
fmt.Println(dog.name, "吃骨头")
}
func (cat Cat) eat() {
fmt.Println(cat.name, "吃鱼")
}
func (cat Cat) sleep() {
fmt.Println(cat.name, "睡着了")
}
func main() {
//创建一个狗
dog := Dog{"大黄", 2}
dog.eat()
//创建一个猫
cat := Cat{"大花", 3}
cat.eat()
cat.sleep()
}
5.方法的重写
/*
方法重写:在父子关系中,方法名称相同叫做重写,方法重写是基于继承的
*/
//定义父结构体
type Animal struct {
name string
age int
}
//定义子结构体
type Dog struct {
Animal
}
type Cat struct {
Animal
}
//定义父类方法
func (animal Animal) eat() {
fmt.Println(animal.name, "吃东西")
}
// 子类重写父类方法
func (dog Dog) eat() {
fmt.Println(dog.name, "吃骨头")
}
func (cat Cat) eat() {
fmt.Println(cat.name, "吃鱼")
}
// 子类除了重写父类方法还可以有自己的方法
func (cat Cat) sleep() {
fmt.Println(cat.name, "睡觉")
}
func main() {
// 创建一个动物对象
animal := Animal{
name: "动物",
age: 2,
}
animal.eat()
// 创建一个猫对象
cat := Cat{
Animal{
"大花",
3,
},
}
cat.eat()
cat.sleep()
}
6.接口
/*
结构体用于定义属性,接口用于定义方法;接口只定义方法,不做方法的实现,结构体实现接口中的所有方法就叫实现了接口;
*/
// 定义接口
type Usb interface {
Input()
Output()
}
//定义结构体
type Mouse struct {
brand string
}
type Keyboard struct {
brand string
}
// 结构体重写接口中的所有方法来实现接口
func (mouse Mouse) Input() {
fmt.Println(mouse.brand, "鼠标输入")
}
func (mouse Mouse) Output() {
fmt.Println(mouse.brand, "鼠标输出")
}
func (keyboard Keyboard) Input() {
fmt.Println(keyboard.brand, "键盘输入")
}
func (keyboard Keyboard) Output() {
fmt.Println(keyboard.brand, "键盘输出")
}
// 定义一个测试函数,传递usb的实现类,自动去判断类型调用相应的方法
func test(usb Usb) {
usb.Input()
usb.Output()
}
func main() {
//创建一个鼠标对象
mouse := Mouse{"罗技"}
test(mouse)
//创建一个键盘对象
keyboard := Keyboard{"樱桃"}
test(keyboard)
}
7.多态
/*
多态: 父类引用指向子类对象
*/
//定义父类接口
type Animal interface {
eat()
sleep()
}
// 定义子类结构体
type Dog struct {
name string
age int
}
type Cat struct {
name string
age int
}
//结构体实现重写接口中所有的方法以实现接口
func (dog Dog) eat() {
fmt.Println(dog.name, "吃骨头")
}
func (dog Dog) sleep() {
fmt.Println(dog.name, "睡着了")
}
func (cat Cat) eat() {
fmt.Println(cat.name, "吃鱼")
}
func (cat Cat) sleep() {
fmt.Println(cat.name, "睡着了")
}
func main() {
//多态
var animal Animal = Dog{"大黄", 2}
animal.eat() // 调用到的是子类重写后的方法
animal.sleep() // 调用到的是子类重写后的方法
}
8.空接口
/*
空接口:实现一个接口就要实现它的所有方法;空接口没有方法,所以所有的东西都实现了空接口,任意
类型都可以赋值给空接口,空接口作为函数的参数可以传递任意类型的数据,空接口还有一个别名叫any。
*/
//定义一个空接口
type I interface {
}
//定义结构体
type Person struct {
name string
age int
}
//定义一个测试函数,空接口作为参数,可以传递任意类型的数据
func test1(i I) {
fmt.Println(i)
}
// 或者直接传递空接口
func test2(i interface{}) {
fmt.Println(i)
}
func main() {
//1.所有的东西都实现了空接口,任意类型都可以赋值给空接口
var i1 I = "字符串"
var i2 I = 3.14
var i3 I = true
var i4 I = Person{"张三", 23}
fmt.Println(i1, i2, i3, i4)
fmt.Println("----------")
//2.空接口作为函数的参数可以接收任意类型的数据
test1("测试")
test1(6.66)
test2(false)
test2(Person{"李四", 24})
fmt.Println("----------")
//3.空接口的别名any做map的值类型,map可以保存任意类型的数据
map1 := make(map[string]any)
map1["name"] = "王五"
map1["age"] = 25
map1["nv"] = Person{"女朋友", 18}
fmt.Println(map1)
fmt.Println("----------")
//4.空接口的别名any做slice的值类型,slice可以保存任意类型的数据
s1 := make([]any, 0)
s1 = append(s1, "字符串", 1, 3.14, true, Person{"赵六", 26})
fmt.Println(s1)
}
9.接口继承:接口可以继承,还可以多继承
// 定义接口
type A interface {
testA()
}
type B interface {
testB()
}
type C interface {
A
B
testC()
}
//定义结构体
type Str struct {
}
//结构体实现接口
func (str Str) testA() {
fmt.Println("testA")
}
func (str Str) testB() {
fmt.Println("testB")
}
func (str Str) testC() {
fmt.Println("testC")
}
func main() {
//子类可以调用实现的所有方法
str := Str{}
str.testA()
str.testB()
str.testC()
//多态:只能调用父接口有的方法
var a A = Str{}
a.testA()
var b B = Str{}
b.testB()
var c C = Str{}
c.testA()
c.testB()
c.testC()
}
10.接口断言:向下转型前需要断言,防止代码报错
//定义接口
type USB interface { //重写接口的所有方法可以实现接口
Input()
Output()
}
// 定义结构体
type Mouse struct {
Brand string
}
type Keyboard struct {
Brand string
}
//结构体重写接口中所有的方法以实现接口
func (mouse Mouse) Input() {
fmt.Println(mouse.Brand + "鼠标输入")
}
func (mouse Mouse) Output() {
fmt.Println(mouse.Brand + "鼠标输出")
}
func (mouse Mouse) ToString() {
fmt.Println("我是鼠标")
}
func (keyboard Keyboard) Input() {
fmt.Println(keyboard.Brand + "键盘输入")
}
func (keyboard Keyboard) Output() {
fmt.Println(keyboard.Brand + "键盘输出")
}
func (keyboard Keyboard) ToString() {
fmt.Println("我是键盘")
}
//类型转换 变量名 := 对象名.(目标类型)
func main() {
//多态的向下转型和断言:多态向下转型可能报错,需要断言
var usb1 USB = Mouse{"达尔优"}
fmt.Println(usb1)
var usb2 USB = Keyboard{"雷蛇"}
fmt.Println(usb2)
fmt.Println("========")
//向下转型:方式一,通过状态判断是不是某个类型
v, ok := usb1.(Mouse)
//v, ok := usb2.(Mouse)
if ok {
v.Input()
v.Output()
v.ToString()
} else {
fmt.Println("对象不是鼠标")
}
fmt.Println("========")
//向下转型:方式二,通过类型匹配到后,需要再转换成响应类型,不然调用不到子类特有的方法
convert(usb2)
}
func convert(para any) {
switch para.(type) {
case pojo.Mouse:
mouse := para.(Mouse)
mouse.Input()
mouse.Output()
mouse.ToString()
case pojo.Keyboard:
keyboard := para.(Keyboard)
keyboard.Input()
keyboard.Output()
keyboard.ToString()
default:
fmt.Println("未找到类型")
}
}
11.自定义类型和给类型起别名
//自定义类型:是一种新的类型,不同类型之间不能运算
type DiyInt int
// 给int起个别名还是int类型
type MyInt = int
func main() {
var i int = 10
var di DiyInt = 20
//fmt.Println(i + di) // 不同类型之间不能运算 invalid operation: i + di (mismatched types int and DiyInt)
fmt.Println(i + int(di)) //可以强转为同一类型后进行运算
var mi MyInt = 30 // 这个是起别名,还是int类型,相同类型之间可以运算
fmt.Println(i + mi)
}