大家好,我是煎鱼。

在大家初识 Go 语言时,总会拿其余语言的根本个性来类比 Go 语言,说白了就是老常识和新常识产生关联,实现更高的学习效率。

最常见的类比,就是 “Go 语言如何实现面向对象?”,进一步开展就是 Go 语言如何实现面向对象个性中的继承。

这不仅在学习中才用到类比,在业内的 Go 面试中也有十分多的面试官喜爱问:

来自读者微信群

在明天这篇文章中,煎鱼带大家具体开展理解这块的常识。一起欢快地开始吸鱼之路。

什么是面向对象

在理解 Go 语言是不是面向对象(简称:OOP) 之前,咱们必须先晓得 OOP 是啥,得先给他 “下定义”。

依据 Wikipedia 的定义,咱们梳理出 OOP 的几个根本认知:

  • 面向对象编程(OOP)是一种基于 "对象" 概念的编程范式,它能够蕴含数据和代码:数据以字段的模式存在(通常称为属性或属性),代码以程序的模式存在(通常称为办法)。
  • 对象本人的程序能够拜访并常常批改本人的数据字段。
  • 对象常常被定义为类的一个实例。
  • 对象利用属性和办法的公有/受爱护/公共可见性,对象的外部状态受到爱护,不受外界影响(被封装)。

基于这几个根本认知进行一步延长出,面向对象的三大根本个性:

  • 封装。
  • 继承。
  • 多态。

至此对面向对象的基本概念解说完结,想更进一步理解的可自行网上冲浪。

Go 是面向对象的语言吗

“Go 语言是否一门面向对象的语言?”,这是一个日经话题。官网 FAQ 给出的回答是:

是的,也不是。起因是:

  • Go 有类型和办法,并且容许面向对象的编程格调,但没有类型档次。
  • Go 中的 "接口 "概念提供了一种不同的办法,咱们认为这种办法易于应用,而且在某些方面更加通用。还有一些办法能够将类型嵌入到其余类型中,以提供相似的货色,但不等同于子类。
  • Go 中的办法比 C++ 或 Java 中的办法更通用:它们能够为任何类型的数据定义,甚至是内置类型,如一般的、"未装箱的 "整数。它们并不局限于构造(类)。
  • Go 因为不足类型档次,Go 中的 "对象 "比 C++ 或 Java 等语言更笨重。

Go 实现面向对象编程

封装

面向对象中的 “封装” 指的是能够暗藏对象的外部属性和实现细节,仅对外提供公开接口调用,这样子用户就不须要关注你外部是怎么实现的。

在 Go 语言中的属性拜访权限,通过首字母大小写来管制:

  • 首字母大写,代表是公共的、可被内部拜访的。
  • 首字母小写,代表是公有的,不能够被内部拜访。

Go 语言的例子如下:

type Animal struct { name string}func NewAnimal() *Animal { return &Animal{}}func (p *Animal) SetName(name string) { p.name = name}func (p *Animal) GetName() string { return p.name}

在上述例子中,咱们申明了一个构造体 Animal,其属性 name 为小写。没法通过内部办法,在配套上存在 Setter 和 Getter 的办法,用于对立的拜访和设置管制。

以此实现在 Go 语言中的根本封装。

继承

面向对象中的 “继承” 指的是子类继承父类的特色和行为,使得子类对象(实例)具备父类的实例域和办法,或子类从父类继承办法,使得子类具备父类雷同的行为。

图来自网络

从理论的例子来看,就是动物是一个大父类,上面又能细分为 “食草动物”、“食肉动物”,这两者会蕴含 “动物” 这个父类的根本定义。

在 Go 语言中,是没有相似 extends 关键字的这种继承的形式,在语言设计上采取的是组合的形式:

type Animal struct { Name string}type Cat struct { Animal FeatureA string}type Dog struct { Animal FeatureB string}

在上述例子中,咱们申明了 CatDog 构造体,其在外部匿名组合了 Animal 构造体。因而 CatDog 的实例都能够调用 Animal 构造体的办法:

func main() { p := NewAnimal() p.SetName("煎鱼,记得点赞~") dog := Dog{Animal: *p} fmt.Println(dog.GetName())}

同时 CatDog 的实例能够领有本人的办法:

func (dog *Dog) HelloWorld() { fmt.Println("脑子进煎鱼了")}func (cat *Cat) HelloWorld() { fmt.Println("煎鱼进脑子了")}

上述例子可能失常蕴含调用 Animal 的相干属性和办法,也可能领有本人的独立属性和办法,在 Go 语言中达到了相似继承的成果。

多态

面向对象中的 “多态” 指的同一个行为具备多种不同表现形式或状态的能力,具体是指一个类实例(对象)的雷同办法在不同情景有不同表现形式。

多态也使得不同内部结构的对象能够共享雷同的内部接口,也就是都是一套内部模板,外部理论是什么,只有合乎规格就能够。

在 Go 语言中,多态是通过接口来实现的:

type AnimalSounder interface { MakeDNA()}func MakeSomeDNA(animalSounder AnimalSounder) { animalSounder.MakeDNA()}

在上述例子中,咱们申明了一个接口类型 AnimalSounder,配套一个 MakeSomeDNA 办法,其承受 AnimalSounder 接口类型作为入参。

因而在 Go 语言中。只有配套的 CatDog 的实例也实现了 MakeSomeDNA 办法,那么咱们就能够认为他是 AnimalSounder 接口类型:

type AnimalSounder interface { MakeDNA()}func MakeSomeDNA(animalSounder AnimalSounder) { animalSounder.MakeDNA()}func (c *Cat) MakeDNA() { fmt.Println("煎鱼是煎鱼")}func (c *Dog) MakeDNA() { fmt.Println("煎鱼其实不是煎鱼")}func main() { MakeSomeDNA(&Cat{}) MakeSomeDNA(&Dog{})}

CatDog 的实例实现了 AnimalSounder 接口类型的束缚后,就意味着满足了条件,他们在 Go 语言中就是一个货色。可能作为入参传入 MakeSomeDNA 办法中,再依据不同的实例实现多态行为。

总结

通过明天这篇文章,咱们根本理解了面向对象的定义和 Go 官网对面向对象这一件事的认识,同时针对面向对象的三大个性:“封装、继承、多态” 在 Go 语言中的实现办法就进行了一一解说。

在日常工作中,根本理解这些概念就能够了。若是面试,能够针对三大个性:“封装、继承、多态” 和 五大准则 “繁多职责准则(SRP)、凋谢关闭准则(OCP)、里氏替换准则(LSP)、依赖倒置准则(DIP)、接口隔离准则(ISP)” 进行深刻了解和阐明。

在阐明后针对上述提到的概念。再在 Go 语言中解说其具体的实现和利用到的基本原理,相互联合解说,就能失去一个不错的成果了。

若有任何疑难欢送评论区反馈和交换,最好的关系是相互成就,各位的点赞就是煎鱼创作的最大能源,感激反对。

文章继续更新,能够微信搜【脑子进煎鱼了】浏览,本文 GitHub github.com/eddycjy/blog 已收录,欢送 Star 催更。

参考

  • Is Go an Object Oriented language?
  • 面向对象的三大基本特征,五大根本准则
  • Go 面向对象编程(译)