Go面向对象编程

面向对象编程

OOP思想

Go语言不是面向对象的语言,只是让大家理解一些面向对象的思想,通过一些方法来模拟面向对象

物以类聚:随着发展变得越来越庞大,我们需要学会归类。

语句多了:我们把一些功能性代码,或者一些完成相同类型作业的代码聚集到一起。函数就出现了

变量多了:相同类型的变量,功能相近的变量放在一起,组合成一个类,结构体就出现了

方法多了、变量多了、结构体也多了。 于是类(伪概念)就出现了。

类:类:模板 --> 具体的对象 (对象)

开发的时候,先开发类,具体使用的时候才是我们的具体对象实例化。

面向过程思维

  • 线性思维
    • 1/2/3/4/5

面向对象思维

  • 分类的思维模式,首先思考这个问题怎么解决,细分成一些不同的类。然后再对类进行单独思考
    • 空天站
      • 地面基地
        • 军方
        • 科研
        • 编码
          • 软件
            • 点火(—一行代码)
          • 硬件
      • 空天基地

公司:

1架构师 CTO:拿到业务,分析需求(分类),架构软件(选型),写接口 面向对象解决问题

10程序员:实现这些接口业务(CRUD) 面向过程解决问题

面向对象:可以解决很多复杂的问题,将现实中的问题,拟人化(用人的思维方式去解决),适合多人协作。

面向过程:适合解决简单的问题。个人就可以完成。

如果我们遇到一个复杂的问题,需要多人协作完成的,面向对象的方式来思考。

**面向对象思维核心就三个点:封装、继承、多态 **

继承

生活中的继承:

兔子和羊属于食草动物类,狮子和豹属于食肉动物类。

食草动物和食肉动物又是属于动物类。

所以继承需要符合的关系是:is-a父类更通用,子类更具体

虽然食草动物和食肉动物都是属于动物,但是两者的属性和行为上有差别,所以子类会具有父类的一般特性也会具有自身的特性

继承就是子类继承父类的特征和行为,使得子类具有父类的属性和方法,使得子类具有父类相同的行为。子类会具有父类的一般特性也会具有自身的特性。

Go语言的继承:结构体的嵌套

/*
Go语言中结构体嵌套
1、模拟继承   is - a

   type A struct{
      field
   }
   type B struct{
      A  // 匿名字段  B.A
      field
   }
   // B是可以直接访问A的属性的

2、聚合关系   has - a

   type C struct{
      field
   }
   type D struct{
      c C  //聚合关系
      field
   }
   // D是无法直接访问C中的属性的,必须使用D.c.c_field
 */

案例:

package main

import "fmt"

// 定义一个父类
type Person struct {
   name string
   age  int
}

// 定义一个子类,Student拥有了父类所有的属性,还有自己的特性
type Student struct {
   Person // 匿名字段,实现了继承。
   school string
}

func main() {
   // 1、 创建父类对象
   p1 := Person{name: "cheng", age: 18}
   fmt.Println(p1)
   fmt.Println(p1.name, p1.age)

   // 2、创建子类
   s1 := Student{Person: Person{name: "小明", age: 3}, school: "学相伴"}
   fmt.Println(s1)
   fmt.Println(s1.Person.name, s1.Person.age, s1.school)

   // 3、创建子类
   var s2 Student
   s2.Person.name = "张三"
   s2.Person.age = 3
   s2.school = "北大"
   fmt.Println(s2)

   // 概念:提升字段, 只有匿名字段才可以做到
   // Person 在Student中是一个匿名字段, Person中的属性 name age 就是提升字段
   // 所有的提升字段就可以直接使用了,不同在通过匿名字段来点了
   
   var s3 Student
   s3.name = "李四"
   s3.age = 4
   s3.school = "清华"
   fmt.Println(s3)
   fmt.Println(s3.name, s3.age)

}

继承就是子类继承父类的特征和行为,使得子类具有父类的属性和方法,使得子类具有父类相同的行为。子类会具有父类的一般特性也会具有自身的特性。

匿名字段 + 提升字段:Go语言中的匿名字段。

方法

Go语言中同时拥有函数和方法。一定要和其他只有方法的语言区分开

类:结构体->属性、方法?

Go语言实现方法

方法:需要指定调用者,约定这个方法属于谁的. 对象.方法()

函数:不需要指定调用者,定义了函数就可以直接函数名()调用

package main

import "fmt"

// 方法:可以理解为函数多了一个调用者
// 方法可以重名,不同的对象,调用的结果是不一样的
type Dog struct {
   name string
   age  int
}

// 方法定义,   func 方法调用者  方法名()
// 1、方法可以重名,只需要调用者不同
// 2、如果调用者相同,则不能重名
func (dog Dog) eat() {
   fmt.Println("Dog eating...")
}

func (dog Dog) sleep() {
   fmt.Println("Dog sleep...")
}

type Cat struct {
   name string
   age  int
}

func (cat Cat) eat() {
   fmt.Println("Cat eating...")
}
func (cat Cat) sleep() {
   fmt.Println("Cat sleep...")
}

func main() {

   // 创建一个对象
   dog := Dog{
      name: "旺财",
      age:  2,
   }
   fmt.Println(dog)
   // 方法的调用,通过对应的结构体对象来调用
   dog.eat()

   cat := Cat{name: "喵喵", age: 1}
   cat.eat()
}

方法:

  • 某个类的行为功能,需要指定调用者
  • 一段独立的代码功能,必须要使用调用者来调用
  • 多个类的方法可以重名,单个类不行
  • 方法是某个类的动作

函数:

  • 一段独立的代码功能,可以直接调用

  • 命名完全不能冲突

  • 函数是一个特殊的类型

方法的重写

需要和继承集合

子类可以重写父类的方法 override

子类还可以新增自己的方法

子类可以访问呢父类中的属性和方法

package main

import (
   "fmt"
)

// 方法重写,建立在父类和子类结构上的
type Animal struct {
   name string
   age  int
}

func (animal Animal) eat() {
   fmt.Println(animal.name, " 正在吃....")
}
func (animal Animal) sleep() {
   fmt.Println(animal.name, " 正在sleep....")
}

// 子类
type Dog struct {
   Animal
}

// 子类自己的方法
func (dog Dog) wang() {
   fmt.Println("wangwangwanwg~~~")
}

type Cat struct {
   Animal
   color string // 子类可以定义自己的属性
}

// 子类重写父类的方法 , 子类的方法名和父类同名,即可重写父类的方法
func (cat Cat) eat() {
   fmt.Println(cat.name, " 正在吃cat....")
}

func main() {
   // 定义一个子类,使用父类方法
   dog := Dog{Animal{name: "旺财", age: 3}}
   dog.eat()  // 调用父类的方法
   dog.wang() // 调用自己扩展的方法
   cat := Cat{Animal{name: "煤球", age: 3}, "黑色"}
   cat.eat() // 如果重写了父类的方法就是调用子类自己的方法

   fmt.Println(cat.color) // 调用子类自己的属性

   // 子类可以操作父类的方法,父类可以操作子类的吗?不可以
   // 父类不能调用子类自己的扩展的方法
   a := Animal{name: "大黄", age: 3}
   a.eat()
   a.sleep()

}

接口

package main

import (
   "fmt"
)

// 接口: USB、typec、插座
// 1、Go语言提供了接口数据类型。
// 2、接口就是把一些共性的方法集合在一起定义。
// 3、如果有实现类将接口定义的方法全部实现了,那么就代表实现了这个接口
// 4、隐式实现 Go ,假设A实现了B接口中的所有方法,不需要显示声明
// 5、接口是方法的定义集合,不需要实现具体的方法内容。名字约束

// 接口的定义 interface 来定义,方法太多了,要归类,方法的集合
type USB interface { // 接口,方法的集合
   input()  // 输入方法
   output() // 输出方法
}

// 结构体
type Mouse struct {
   name string
}

// 结构体实现了接口的全部方法就代表实现了这个接口,否则不算实现这个接口
func (mouse Mouse) output() {
   fmt.Println(mouse.name, "鼠标输出")
}
func (mouse Mouse) input() {
   fmt.Println(mouse.name, "鼠标输入")
}

// 接口嗲用测试
func test(u USB) {
   u.input()
   u.output()
}

func main() {
   // 通过传入接口实现类来进行调用
   m1 := Mouse{name: "罗技"}
   // test 参数 USB 类型,如果一个结构体实现了这个接口所有的方法,那这个结构体就是这个接口类型的
   test(m1)

   k1 := KeyBoard{name: "雷蛇"}
   test(k1)

   // 定义高级类型  k1就升级了  KeyBoard --> USB  向上转型
   var usb USB
   usb = k1
   fmt.Println(usb)
   // 接口是无法使用实现类的属性的
   //fmt.Println(usb.name)

}

// 结构体
type KeyBoard struct {
   name string
}

// 结构体实现了接口的全部方法就代表实现了这个接口,否则不算实现这个接口
func (key KeyBoard) output() {
   fmt.Println(key.name, "键盘输出")
}
func (key KeyBoard) input() {
   fmt.Println(key.name, "键盘输入")
}

模拟多态

多态:一个事务有多种形态

父类:动物
子类:猫
子类:狗

猫和狗是多态的,他们既可以是自己,也可以是动物,这个就是多态,一个事务有多种形态
package main

import "fmt"

// 定义接口
type Animal interface {
   eat()
   sleep()
}

type Dog struct {
   name string
}

func (dog Dog) eat() {
   fmt.Println(dog.name, "--eat")
}
func (dog Dog) sleep() {
   fmt.Println(dog.name, "--sleep")
}

// 多态
func main() {

   // Dog 两重身份:1、Dog   2、Animal ,多态
   dog1 := Dog{name: "旺财"}
   dog1.eat()
   dog1.sleep()

   // Dog 也可以是 Animal
   test2(dog1)

   // 定义一个类型可以为接口类型的变量
   // 实际上所有实现类都可以赋值给这个对象
   var animal Animal // 模糊的 -- 具体化,将具体的实现类赋值给他,才有意义
   animal = dog1
   test2(animal)
}

// Animal 接口
func test2(a Animal) {
   a.eat()
   a.sleep()
}

接口的实现类都拥有多态特性:除了自己本身还是他对应接口的类型。

空接口

不包含任何方法

因此:所有的结构体都默认实现了空接口

因此空接口可以存储任何的类型

interface{}  == any 
package main

import "fmt"

type A interface{}
type Dogg struct {
   name string
}
type Catt struct {
   name string
}

func testNow(a A) {
   fmt.Println(a)
}

// 可以指定定义空接口
// // any is an alias for interface{} and is equivalent to interface{} in all ways.
//type any = interface{}
func testNow2(temp interface{}) {
}

func main() {
   var a1 A = Catt{name: "喵喵"}
   var a2 A = Dogg{name: "旺财"}
   var a3 A = 1
   var a4 A = "xuexiangban"
   fmt.Println(a1)
   fmt.Println(a2)
   fmt.Println(a3)
   fmt.Println(a4)

   // map
   map1 := make(map[string]interface{})
   map1["name"] = "qinjiang"
   map1["age"] = 18
   fmt.Println(map1)

   // slice
   s1 := make([]any, 0, 10)
   s1 = append(s1, 1, "12312", false, a1, a2)
   fmt.Println(s1)

   var arr [4]interface{}
   fmt.Println(arr)

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值