010.Go语言中的面向对象

目录

1.Go语言中的面向对象

2.继承

3.聚合

4.方法

5.方法的重写

6.接口

7.多态

8.空接口

9.接口继承

10.接口断言

11.自定义类型和给类型起别名


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)

}
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值