面向对象

 

面向对象的概念

洗衣服过程剖析:

  1. 给洗衣机里加脏衣服和洗衣粉。

  2. 启动洗衣机。

  3. 洗衣机自动注水,然后滚动。

  4. 脏衣服从黑颜色变成白颜色。

  5. 洗衣机自动停止。

用面向过程的思想实现代码。

//准备洗衣服
//输入参数:
//powder 洗衣机里放多少洗衣粉
//closes 洗衣机里放多少衣服
//clean 衣服是否是干净的
//返回值:
//洗衣机是否开启
//准备洗多少衣服
func prepare(powder int, closes int, clean bool) (bool, int) {
    if powder <= 0 || closes <= 0 || clean == true {
        return false, 0
    }
    return true, closes
}
​
//开始洗衣服
//输入参数:
//washer_state 洗衣机是否开启
//closes 准备洗多少衣服
//返回值:
//衣服是否是干净的
//洗了多少衣服
//洗衣机是否开启
func wash(washer_state bool, closes int) (bool, int, bool) {
    if washer_state == false {
        return false, 0, false
    } else {
        fmt.Println("注水")
        fmt.Println("滚动")
        fmt.Println("关机")
        return true, closes, false
    }
}
​
//检查最终状态
//输入参数:
//clean 衣服是否是干净的
//closes 洗了多少衣服
//washer_state 洗衣机是否开启
func check(clean bool, closes int, washer_state bool) {
    if clean && closes > 0 {
        fmt.Printf("洗干净了%d件衣服\n", closes)
        if washer_state {
            fmt.Println("你忘关洗衣机了")
        }
    } else {
        fmt.Println("洗衣失败")
    }
}
​
//整个洗衣服的过程
func WashProcedure(powder, closes int) {
    washer_state := false
    clean := false
​
    washer_state, closes = prepare(powder, closes, clean)
    clean, closes, washer_state = wash(washer_state, closes)
    check(clean, closes, washer_state)
}

面向过程编程整个过程分为若干步,每一步对应一个函数,函数之间要传递大量的参数。 面向对象编程把大量参数封装到一个结构体里面,给结构体赋予方法,方法里面去修改结构体的成员变量。go语言面向对象的好处:打包参数,继承,面向接口编程。

//洗衣机
type Washer struct {
    State  bool
    Powder int
}
​
//衣服
type Closes struct {
    Clean bool
}
​
func (washer *Washer) prepare(closes []*Closes) error {
    if washer.State == true || washer.Powder <= 0 || len(closes) <= 0 {
        return errors.New("请确保在关机的状态下加入适量衣物和洗衣粉")
    }
    return nil
}
​
func (washer *Washer) wash(closes []*Closes) error {
    if err := washer.prepare(closes); err != nil {
        return err
    }
​
    fmt.Println("开机")
    washer.State = true
​
    //检查是否有脏衣服
    clean := true
    for _, ele := range closes {
        if ele.Clean == false {
            clean = false
            break
        }
    }
    if clean {
        washer.State = false
        return errors.New("所有衣服都是干净的,不需要洗")
    }
​
    //开始洗衣服
    fmt.Println("注水")
    fmt.Println("滚动")
    fmt.Println("关机")
    washer.State = false
    for _, ele := range closes {
        ele.Clean = true
    }
    return nil
}
​
func (washer *Washer) check(err error, closes []*Closes) {
    if err != nil {
        fmt.Printf("洗衣失败:%v\n", err)
    } else {
        fmt.Printf("洗干净了%d件衣服\n", len(closes))
        if washer.State == true {
            fmt.Println("你忘关洗衣机了")
        }
    }
}

构造函数

定义User结构体。

type User struct {
    Name string //""表示未知
    Age int //-1表示未知
    Sex byte //1男,2女,3未知
}
  • u := User{}构造一个空的User,各字段都取相应数据类型的默认值。

  • up := new(User)构造一个空的User,并返回其指针。

自定义构造函数

func NewDefaultUser() *User {
    return &User{
        Name: "",
        Age: -1,
        Sex: 3,
    }
}
func NewUser(name string, age int, sex byte) *User {
    return &User{
        Name: name,
        Age: age,
        Sex: sex,
    }
}

单例模式,确保在并发的情况下,整个进程里只会创建struct的一个实例。

var (
    sUser *User
    uOnce sync.Once
)
func GetUserInstance() *User {
    uOnce.Do(func() { //确保即使在并发的情况下,下面的3行代码在整个go进程里只会被执行一次
    if sUser == nil {
        sUser = NewDefaultUser()
        }
    })
    return sUser
}
​
//调用GetUserInstance()得到的是同一个User实例
su1 := GetUserInstance()
su2 := GetUserInstance()
//修改su1会影响su2

继承与重写

通过嵌入匿名结构体,变相实现“继承”的功能,因为访问匿名成员时可以跳过成员名直接访问它的内部成员。

type Plane struct {
    color string
}
type Bird struct {
    Plane 
}
bird := Bird {}
bird.Plane.color
bird.color

重写

func (plane Plane) fly() int {
    return 500
}
​
//重写父类(Plane)的fly方法
func (bird Bird) fly() int {
    return bird.Plane.fly()+100 //调用父类的方法
}

正规来讲,Go语言并不支持继承,它只是支持组合。

type Plane struct {}
type Car struct{}
//Bird组合了Plane和Car的功能
type Bird struct {
	Plane 
	Car
}

泛型

在有泛型之前,同样的功能需要为不同的参数类型单独实现一个函数。

func add4int(a, b int) int {
	return a + b
}
func add4float32(a, b float32) float32 {
	return a + b
}
func add4string(a, b string) string {
	return a + b
}

使用泛型

type Addable interface{
type int, int8, int16, int32, int64,
	uint, uint8, uint16, uint32, uint64, uintptr,
	float32, float64, complex64, complex128,string
}
func add[T Addable](a,b T)T{
	return a+b
}

在go1.17中泛型默认没有开启,如果想用需要加-gcflags=-G=3,或者设置环境变量export GOFLAGS="-gcflags=-G=3"。泛型正式版将在go 1.18中发布,但是Go语言之父Rob Pike建议不在Go 1.18的标准库中使用泛型。

posted @ 2022-09-10 22:37  屠魔的少年  阅读(3)  评论(0)    收藏  举报