Go【No-13】面向对象

本文介绍了Go语言如何实现面向对象的编程思想,包括封装、继承和多态。在Go中,封装通过结构体和标识符首字母大小写实现,继承则通过结构体嵌套模拟,多态依赖于接口和鸭子类型。文章还展示了Java和Go语言中实现面向对象的对比,并探讨了单例模式在Go中的应用。
摘要由CSDN通过智能技术生成

13-面向对象

面向对象三大特性:封装、继承、多态

Golang 没有类的概念,也没有面向对象的概念。
准确的说,面向对象、封装、继承、多态、抽象等等,这些都是编程思想,不同的语言实现这些特性的方式不同。

例如 Java,用的是类 class,访问修饰符 public、protected、default、private 等来实现;
在 Golang 中,用的是结构体 struct、标识符首字母大小写 等来实现。

面向过程、面向对象、一切皆对象、一切皆文件 等诸如此类的概念,
在学习之初可能会成为初学者的一道坎,也可能是帮助新手更快入门的好帮手;
等到学到一定程度以后,这些思想能帮助我们快速解决一些问题,也可能开始禁锢我们的思想;
善于变通者会慢慢看透本质,脱离这些思想的枷锁,对编程形成自己的认知。
变通者和不变通者的区别在于:是否愿意深入底层(汇编、组原等等),是否愿意摒弃语言执念。

  1. 封装
    • 封装也叫信息隐藏、数据访问保护。通过暴露有限的访问接口,外部仅能通过类提供的方式来访问内部信息或数据。
    • 需要编程语言提供权限访问控制语法来支持。如:
      • Java 中的 public、protected、private
      • Python 中标识符的双下划线前缀 __xxx__slots__ 白名单
      • Golang 中标识符首字母大小写。
    • 封装存在的意义,
      • 一方面是保护数据不被随意修改,提高代码可维护性;
      • 一方面是仅暴露有限的必要接口,提高易用性。
  2. 抽象
    • 封装讲的是如何隐藏信息、保护数据,抽象讲的就是如何隐藏的具体实现。
    • 抽象可以通过接口类或者抽象类来实现,但不需要特殊的语法机制来支持。
    • 抽象存在的意义,
      • 一方是是提高代码的可扩展性、维护性,修改实现不需要修改定义,减少代码改动范围;
      • 另一方面,抽象也是处理复杂系统的有效手段,能有效过滤掉不必关注的信息。
  3. 继承
    • 继承是用来表示类之间的 is-ahas-a 的关系,分为两种模式:单继承和多继承。
    • 单继承表示一个子类只能继承一个父类,多继承表示一个子类可以继承多个父类。
    • 需要编程语言提供特殊语法机制来支持。如:
      • Java 中的 extends 关键字
      • Python 中类名后的括号
      • Go 中的结构体嵌套
    • 继承存在的意义,是用来解决代码复用的问题。
  4. 多态
    • 多态是指子类可以替代父类。在实际代码运行过程中,调用子类的方法实现。
    • 需要编程语言提供特殊语法机制来支持。如:继承、接口、duck-typing。
    • 多态可以提高代码的扩展性和复用性,是很多设计模式、设计原则、编程技巧的代码实现的基础。

封装

在 Java 等面向对象中,会将一类事物抽象出属性行为,并通过语言层面限定 访问性

属性 使用基本数据类型或复合类型描述;
行为 通过函数描述,并称之为方法
属性+方法组成一个类class
访问性各个语言实现不同。

在 Go 中没有类的概念,
而是将事物的 属性 使用基本数据类型或复合数据类型 封装在结构体中
行为 是通过 给函数限定调用者的方式 实现。
访问性 是通过首字母大写为 public,首字母小写为 private

这种限定了调用者的函数,我们称之为方法
而拥有方法的结构体,我将其称之为

Golang 中,类 = 结构体 + 限定调用者的函数 + 访问性

// class A

type A struct {
   
    fieldA
}

func (a A) aMethod() {
   
    ...
}

构造函数

Go 不支持像 Java 那样的构造函数,但是可以通过 标识符首字母大小写 + 工厂函数 实现构造函数。

一般分为4步:

  1. 将结构体、字段的首字母小写
  2. 结构体所在的包提供一个工厂模式的函数,首字母大写,模拟一个构造函数。按照规范,构造函数的名字以 newNew 开头。注意返回值必须是结构体指针,因为结构体是值类型。
  3. 提供首字母大写的 Get 方法,用于获取属性的值
  4. 提供首字母大写的 Set 方法,用于设置属性的值

eg:

type person struct {
   
    name string
    age  int
}

// 写一个工厂函数,首字母大写,其他方就可以访问,相当于构造函数
func NewPerson (name string, age int) (*person, error) {
   
    if age <= 0 || name == "" {
    
    	return nil, errors.New("Parameters Error.") 
   	}
    return &person{
   name, age}, nil
}

// Get 方法
func (p person) GetName() string{
   
    return p.name
}

func (p person) GetAge() int {
   
    return p.age
}
// Set 方法
func (p person) SetName(name string) error {
   
    if name == "" {
    
    	return errors.New("Parameters Error.") 
    }
    p.name = name
    return nil
}

func (p person) SetAge(age int) error {
   
    if age <= 0 {
    
    	return errors.New("Parameters Error.") 
    }
    p.age = age
    return nil
}


func main() {
   
    // 然后这样创建对象:
    p := NewPerson("Boii", 18)
    fmt.Println(p)    // &{Boii 18}

    p.GetName()     // Boii
    p.SetAge(
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

TCP404

老板大方~

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值