教程集 www.jiaochengji.com
教程集 >  Golang编程  >  golang教程  >  正文 Go 面向对象式编程

Go 面向对象式编程

发布时间:2022-01-14   编辑:jiaochengji.com
教程集为您提供Go 面向对象式编程等资源,欢迎您收藏本站,我们将为您提供最新的Go 面向对象式编程资源
<blockquote>

『就要学习 Go 语言』系列 -- 第 25 篇分享好文

</blockquote>

Go 语言没有对象的概念,但是 struct 类型有着和对象类似的特性。struct 类型可以定义自己的属性和方法。这篇文章我们来总结下 Go 语言中关于 “继承” 和多态的概念。

<h3 class="heading" data-id="heading-0">嵌入类型</h3>

嵌入类型是指将已有的类型直接声明在新的结构类型里。不像 Java、C 等语言,Go 语言没有继承,但是可以通过组合的方式实现代码的复用。

<pre><code class="lang-hljs go copyable" lang="go hljs"><span class="hljs-keyword">type</span> User <span class="hljs-keyword">struct</span> { Name <span class="hljs-keyword">string</span> Email <span class="hljs-keyword">string</span> } <span class="hljs-keyword">type</span> Admin <span class="hljs-keyword">struct</span> { User Level <span class="hljs-keyword">string</span> } <span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-params">(u *User)</span> <span class="hljs-title">Speak</span><span class="hljs-params">()</span></span> { fmt.Println(<span class="hljs-string">"I am user"</span>,u.Name) } <span class="copy-code-btn">复制代码</span></code></code></pre>

上面的代码定义了两个结构体 User 和 Admin,Admin 有一个匿名成员 User,因为是匿名,所以类型即名称。将 User 嵌入 Admin,Admin 是被嵌入的类型,也称外部类型,User 是内部类型。Speak() 是 User 的方法。

通过嵌入,内部类型的属性、方法,可以为外部类型所有,就好像是外部类型自己的一样。此外,外部类型还可以定义自己的属性和方法,甚至可以定义与内部相同的方法,这样内部类型的方法就会被“屏蔽”。

<pre><code class="lang-hljs go copyable" lang="go hljs">admin := Admin{ User:User{ Name:<span class="hljs-string">"Jack"</span>, Email:<span class="hljs-string">"Jack@gmail.com"</span>, }, Level:<span class="hljs-string">"admin"</span>, } <span class="hljs-comment">// 内部类型的方法也被提升到外部类型</span> admin.Speak() <span class="hljs-comment">// 方式一</span> <span class="hljs-comment">// 直接访问内部类型的方法</span> admin.User.Speak() <span class="hljs-comment">// 方式二</span> <span class="copy-code-btn">复制代码</span></code></code></pre>

输出:

<pre><code class="lang-hljs go copyable" lang="go hljs">I am user Jack I am user Jack <span class="copy-code-btn">复制代码</span></code></code></pre>

给 Admin 定义自己的 Speak() 方法:

<pre><code class="lang-hljs go copyable" lang="go hljs"><span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-params">(a *Admin)</span> <span class="hljs-title">Speak</span><span class="hljs-params">()</span></span> { fmt.Println(<span class="hljs-string">"I am admin"</span>,a.Name) } <span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">main</span><span class="hljs-params">()</span></span> { admin := Admin{ User:User{ Name:<span class="hljs-string">"Jack"</span>, Email:<span class="hljs-string">"Jack@gmail.com"</span>, }, Level:<span class="hljs-string">"admin"</span>, } admin.Speak() <span class="hljs-comment">// 方式一</span> admin.User.Speak() <span class="hljs-comment">// 方式二</span> } <span class="copy-code-btn">复制代码</span></code></code></pre>

输出:

<pre><code class="lang-hljs go copyable" lang="go hljs">I am admin Jack I am user Jack <span class="copy-code-btn">复制代码</span></code></code></pre>

可以看到,Admin 定义了自己的 Speak() 方法时,会自动调用自己的方法,而屏蔽内部类型的方法。对于属性也是一样的情况。
查看完整代码

另外,更重要的是,如果内部类型实现接口 A,也可以认为外部类型也实现了接口 A。

<pre><code class="lang-hljs go copyable" lang="go hljs"><span class="hljs-keyword">type</span> Speaker <span class="hljs-keyword">interface</span> { Speak() <span class="hljs-comment">// 方法</span> } <span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">gotoSpeak</span><span class="hljs-params">(s Speaker)</span></span> { s.Speak() } <span class="copy-code-btn">复制代码</span></code></code></pre>

定义了 Speaker 接口,任意类型如果实现了接口中定义的全部方法,就认为该类型实现了接口。例如,上面定义的 User 类型,就实现了接口 Speaker。gotoSpeak() 函数是接收 Speaker 接口类型的参数,任何实现了 Speaker 接口的类型都可以调用该函数。

<pre><code class="lang-hljs go copyable" lang="go hljs">admin := Admin{ User: User{ Name: <span class="hljs-string">"Jack"</span>, Email: <span class="hljs-string">"Jack@gmail.com"</span>, }, Level: <span class="hljs-string">"admin"</span>, } gotoSpeak(&admin) <span class="copy-code-btn">复制代码</span></code></code></pre>

输出:

<pre><code class="lang-hljs go copyable" lang="go hljs">I am user Jack <span class="copy-code-btn">复制代码</span></code></code></pre>

注意,关键点来了,调用 gotoSpeak() 时传的参数是 admin 的地址,类型是 *Admin,不能传 Admin 类型的值。从上篇文章我们知道,Admin 类型的方法集中不包括 Speak() 方法,也就是说 Admin 类型没有实现 Speaker 接口。

结合上篇关于类型方法集,对于嵌入类型的内部类型方法的提升可以总结下。假设外部结构体类型是 S,内部类型是 T,则关于内部类型的方法提升如下规则:

<ol><li>T 嵌入 S,外部类型 S 可以通过值类型或指针类型调用内部类型 T 的值方法;</li> <li>T 嵌入 S,外部类型 S 只能通过指针类型调用内部类型 T 的指针方法;</li> <li>*T 嵌入 S,外部类型 S 可以通过值类型和指针类型调用内部类型 T 的值方法和指针方法;</li> </ol>

上面的三条规则可以总结成一句话:不管是 T 嵌入 S,还是 *T 嵌入 S,外部类型 S 唯独通过值类型不能调用内部类型 T 的指针方法外,其他情况下内部类型 T 的方法都可以获得提升,即可被外部类型 S 访问 。

前两点其实很好理解,第三点是通过指针方式组合,其实就是在外部类型初始化的时候,取得内部类型的指针。其他规则与非指针方式组合一致。

<pre><code class="lang-hljs go copyable" lang="go hljs"><span class="hljs-keyword">type</span> Admin <span class="hljs-keyword">struct</span> { *User <span class="hljs-comment">// 通过指针方式组合</span> Level <span class="hljs-keyword">string</span> } <span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">main</span><span class="hljs-params">()</span></span> { admin := Admin{ User: &User{ Name: <span class="hljs-string">"Jack"</span>, Email: <span class="hljs-string">"Jack@gmail.com"</span>, }, Level: <span class="hljs-string">"admin"</span>, } gotoSpeak(&admin) gotoSpeak(admin) } <span class="copy-code-btn">复制代码</span></code></code></pre>

输出:

<pre><code class="lang-hljs go copyable" lang="go hljs">I am user Jack I am user Jack <span class="copy-code-btn">复制代码</span></code></code></pre><h3 class="heading" data-id="heading-1">多态</h3>

其实上面的例子已经给出多态的例子了,这个给大家提一下。在 Go 语言中,每种类型都是不同的,但不同的类型可以实现同一接口,将它们绑定在同一接口上,用作函数或者放的输入(输出)参数。例如上面的 User 类型和 Admin 类型就是通过 Speaker 接口建立了关系。

深入阅读:
1.教女朋友写方法(续)
2.Polymorphism - OOP in Go
3.Is Go An Object Oriented Language?
4.《Go 语言实战》5.4 5.5 节


(全文完) <blockquote>

原创文章,若需转载请注明出处!
欢迎扫码关注公众号「Golang来啦」或者移步 seekload.net ,查看更多精彩文章。

</blockquote>

给你准备了学习 Go 语言相关书籍,公号后台回复【电子书】领取!

<figure><figcaption/></figure>


到此这篇关于“Go 面向对象式编程”的文章就介绍到这了,更多文章或继续浏览下面的相关文章,希望大家以后多多支持JQ教程网!

您可能感兴趣的文章:
go语言和python哪个难
Go核心编程-面向对象 [OOP]
Go语言学习3----Go语言特色
golang是面向对象吗_Go是面向对象的吗?
Go语言发展历史、核心、特性及学习路线
关于Golang的介绍
Go 语言设计模式系列之一 ——Go 语言中的面向对象
龙芯平台构建Go语言环境指南
go 语言学习历程
探讨 Go语言之面向对象特性:多态 设计思路和实际编程

[关闭]
~ ~