10.面向对象

    在学习接口时,已经接触了一些面向对象的概念,在这个章节中,我们来重点学习一下面向对象的相关概念。

    面向对象程序设计(OOP:Object-oriented programming)是一种具有对象概念的编程典范,同时也是一种程序开发的抽象方针,包含数据、特性、代码与方法。主要涉及两个核心概念。

  • 类(Class): 根据某类事物的共同特征高度抽象出一种类型。例如动物、人类等
  • 对象(Object): 是类的一个具体实现,即类的实例。例如:人类是一个类,而具体的一个人(例如:小明)则是人类的一个实例,一个类可以拥有很多个实例

    面对对象的核心三要素如下所示:

  • 封装:将属性(数据)和方法(操作)封装,提供访问控制,隐藏实现的细节,仅对外暴露必要的接口
  • 继承:子类可以从父类直接获取属性和方法,减少重复定义。若子类与父类有不同,可以自己重新定义新的属性和方法,也可以覆盖父类的同名属性和方法
  • 多态:父类和子类虽使用同一个方法,但不同子类表现却不一样,就是不同的态。可以简单理解为龙生九子,但各有所好

    只有实现了以特征的语言,才能算是面向对象编程范式的语言。所以从严格意义上来讲,Go并不是面向对象编程范式的语言,但却以借鉴了面向对象的一些特征,Go语言通过组合的方式实现了类似的功能。

10.1 封装

    通过结构体,可以将数据字段封装在里面,也可以为结构体绑定方法。还可以进行访问控制。

  • 字段、方法标识符首字母大写,实现包外可见的访问控制
  • 字段、方法标识符首字母小写,仅包内可见

通过首字母的大小写,实现类似于Java中的public和private访问控制

10.2 继承

    Go语言没有提供继承语法,但可以结构体嵌套来达到类似效果。

10.3 多态

    Go语言不能像Java语言那样使用多态,但可以通过引入接口来达到类似的效果,示例代码如下所示:

package main

import "fmt"

type Run interface {
	Run() string
}

type Animal struct {
	Name string
}

func (a *Animal) Run() string {
	return fmt.Sprintf("Animal:%s is running", a.Name)
}

type Cat struct {
	// 结构体嵌套
	Animal
	Color string
}

func (c *Cat) Run() string {
	fmt.Printf("%s is running,color is: %s\n", c.Name, c.Color)
	return c.Animal.Run()
}

type Dog struct {
	Animal
	Type string
}

func (d *Dog) Run() string {
	fmt.Printf("%s is running,type is: %s\n", d.Name, d.Type)
	return d.Animal.Run()
}

func test(a Run) {
	// 多态
	fmt.Println(a.Run())
}

func main() {
	d := &Dog{Animal: Animal{Name: "小黄"}, Type: "柯基"}
	c := &Cat{Animal: Animal{Name: "小花"}, Color: "黄色"}
	test(d)
	test(c)
}

    运行结果如下所示:

小黄 is running,type is: 柯基
Animal:小黄 is running
小花 is running,color is: 黄色
Animal:小花 is running

    方法test使用同一个类型的同一接口却表现不同,这就是多态。

10.4 覆写

    即子类通过定义一个与父类同名的方法,达到重写的功能,示例代码如下所示:

package main

import "fmt"

type Animal struct {
	Name string
}

func (a *Animal) Run() string {
	return fmt.Sprintf("Animal:%s is running", a.Name)
}

type Cat struct {
	// 结构体嵌套
	Animal
	Color string
}

func (c *Cat) Run() string {
	return fmt.Sprintf("Cat:%s is running", c.Name)
}

func main() {
	c := &Cat{Animal: Animal{Name: "小花"}, Color: "黄色"}
	// 调用子类自身的Run方法
	fmt.Println(c.Run())
	// 调用父类的Run方法
	fmt.Println(c.Animal.Run())
}

    运行结果如下所示:

Cat:小花 is running
Animal:小花 is running

在上面代码通过为Cat增加一个Run方法,从而覆盖了父类的Run方法,从而达到不依赖父类结构体方法。

本文同步在微信订阅号上发布,如各位小伙伴们喜欢我的文章,也可以关注我的微信订阅号:woaitest,或扫描下面的二维码添加关注:

posted @ 2025-08-17 23:59  Surpassme  阅读(13)  评论(0)    收藏  举报