00:00
那我们来看一下继承的深入讨论,那关于承这一块呢,我们还有一些就是比较深入的一些东西要跟他探讨一下,那大家看第一个哈,就说。嗯,结构体可以使用嵌套匿名结构体所有的字段和方法,这一点大家注意,就是说不管你这个首字母是大写的还是小写的。字段或方法都可以用。这个跟我们有些编程语言不一样,比如说你不能用那个O传统的编程语言来说,呃,比如说Java Java它私有的,其实你在这个子类里面是用不了的,但是呢,在勾浪里边它这样子的啊,就说他一旦把这个嵌套匿名结构体这个写进去了,那么你这个嵌套匿名结构体的所有的字段和方法,不管是首字母大写还是小写都可以使用。那这块呢,我给大家做一个啊,做一个这个这个演示。好,同学们看一下啊,那现在我们还是说这个继承的事,继承的深入讨论对不对。
01:01
好,我们来一个标题三。进行深入讨论。第一点。借深入深入讨论第一点,那么我给大家举个例子。这些大家要把它弄明白,搞清楚哈,那为了讲解这个东西呢,我们就新建一个文件夹。新建一个chapter。幺零,那么我们现在讲的是继承的一个细节,对吧,Details。好,然后呢,我们给它来一个文件对吧,文件面顶go。OK。啊,同样我们把一些共用的部分拿过来用一下。走到这来。好,写一个function主函数。主函数。呃,那现在呢,我们来看这么一个情况,比如说我这里有个A。A,这是个结构体,那这个结构体里边呢,我们定义一个字段叫name。我把它做成一个。首字母大写的对不对,然后呢,我再写个age,这个age呢,我们把它做成一个小写的,好,这写完了,紧接着呢,我们来写两个方法,给它绑定两个方法注意看啊,嗯,Function function。
02:14
然后呢,我们再写个A,新A没问题吧,然后我写一个方法叫做C。COK,好,COK,这个是来个大写吧,先好吧,COK,然后我们输出一句话。标体。好,我们输出这么一句话叫做什么呢?呃,写到这儿写写到这吧,叫做叫做这个A绑定的A里面的这个COK。OK,好,你如果愿意的话呢,可以把这个名字说出来一下好吧。这就写完了,我们再写一个方法。还是跟这个A的。呃,这个指针类型绑定。大家看一下A,大写的A。
03:02
就写多了一个,然后呢,我们再来写一个叫做什么呢哈,是个小写的。Hello。好的,然后呢,我把这个地方也复制一份放下来,好吧,大家看一下,那这边写个A里面的叫做hello。也是一个名字,大家看到这里面字段,字段有个大手中的大写,有一个小写,我们的绑定的方法有一个大写有个小写,好我们现在呢用一个type b。Type b,好,在这个结构体里边,我们嵌入这个默认的结构体A,大家看清楚没有,好,现在呢,我们来看看在B里面我们可以用到A的哪一些字段和哪些这个方法,好吧,那我现在来定义一个。VR2B,那这样直接写个RB。对不对,也可以这样写,非常简单的一种方式,就B。这样子是不是也可以啊?是不是这样,这样是不是也可以啊,这样也可以,是不是我就定义定义了一个B这样的一个结构体类型,是吧?那么现在我们来用一下啊B点我我先去用用他的名字,我们看看能不能访问他的名字a.name。
04:12
给他一个名字吧,比如说叫汤姆。b.a点它小写的年龄来19。好,我们再来。用下它两个方法对不对?b.a里面的大写的c hello。没问题吧,然后b.a里面小写的hello。好,我们来看看这个时候是不是都可以都可以使用成功,好,我们来运行一下。CD点点CD到里面的这个细节,Detail。对不对。好,然后呢,我们go run main.go跑起来,我们看代码有没有问题,我们发现完全没有问题A。C hello,汤姆a hello,汤姆,正确,那就证明我们一个观点,什么观点呢?就是你这个结构体可以使用,使用匿名结构体里面所有的字段和方法,我不管你是大写还是小写,这一点大家都要搞清楚啊,到时间别把这个搞蒙圈了,因为呃,我们有些同学学过编程语言,他知道那个私有的其实是不能在外面使用的,对吧,但是呢,这点我们说了,Go浪里面它不存在这个问题,他可以直接使用啊,都可以用好,我把这个呢给大家板述一下。
05:31
好到我们的第26行。好的板书一板。然后呢,我们接着截取下面的27行。好,27行。从这到这面结束。好,整体把它拿过来为我所用,对吧,可以可以写完,那么这个做完了过后,我们再来看他的深入讨论。第二点,匿名结构体字段访问可以简化,你比如说大家看我这里面写的东西。
06:01
比如说我们这样反问A。AA,其实呢,你也可以直接把这个大写的A去掉,把这个也是,也就是说把这个匿名结构体去掉,你也可以直接b name BB cb哈,为什么可以这样用呢?原因是因为你本身这个B。B的这个结构体里面其实是没有name age c和hello这个方法的,因此你也可以直接跳过,因为这个编译器他在找的时候呢,他先到这个B里面,他找到这个B,它是一个结构体,是个B这个结构体他就去找,诶你这个结构体里面有没有name。如果没有的话,他就看嵌入,他就会去看你嵌入的结构体里面有没有这个内幕字段,或者是A这个字段,明白吧,同样方法也是一样的,因此呢,在这种情况下其实可以简化,也就是说实际上我们前面这种写法完全可以等价这种写法。就说上面。上面的写法可以简化。
07:02
简化成什么呢?注意啊。它可以简化成下面的写法。比如说同学们看。我重新来给他赋一下值,比如说这个name,我重新赋一个值叫做什么呢?史密斯?好,他的年龄呢,我也给他来重新设一下,叫20。好,同样我也通过这个B这个变量直接调用c hello,那有些同学可能会说,诶老师这个你这c hello不是跟A绑定的吗?怎么用B就可以调用呢。我再说一遍啊,就是因为这个BB这个变量,它是这个B结构体吗?他到这里面去找,他发现这个他自己是没有,但是他发现有个嵌入结,有一个嵌入的这个结构体,他就会去看这个A有没有这样的方法,明白吧,如果找到了他也会去调用。也就是他先到B里面去看有没有这个方法,就他去看你这个B有没有绑定一个叫c hello的,如果没有,我就到他的嵌入的这个结构体里面去看有没有,如果有就调用,那如果两个都没有,那就报错了。
08:04
他说这个函数没定义,明白这意思吧,好,我把这个改一下,同学们看我们代码执行版,我们会会发现代码没有任何问题。是不是?没有任何问题吧?COK,史密斯,C hello,史密斯,完全正确。好,这也就是又一个细节,又一个细节,好,关于这个细节呢,我们把它整理到我们的笔记里面去。啊,这些都是我们后面这个写项目的时候都需要用到的啊,不然的话,别人写这个东西你就看不懂了。好,我把这个说明代码呢给大家整理出来。好吧。OK。好,那么他们的这个关系呢,就是这样子的。这个和这个写法。可以。好,我把这个代码拿过来过后呢,我对它做一个总结,对上面这个代码做一个总结,好吧,就小结一下。对上面的代码小结一下。
09:01
那小结地方呢,我有这么几点要给大家,呃,单独的说一下第一个。就是当我们调用啊,当我们这样调用啊调用。当我们直接通过B访问。放啊。访问什么呢?访问这个字段或方法时,方法时其执行流程,执行流程如下。比如我们B。B点内它会怎么做呢?他先这编译器啊,编译器会先看,先看这个B对应的对应的这个类型。它对应。对应的这个类型有没有这个name字段。你你这个B不是对应一个类型叫大大写的B吗?他看有没有这个类目,如果有啊,如果有则则直接直接调用。调用啊,调用这个什么呢?BB这个类型的,B这个类型的啊。
10:06
类型的这个什么呢?Name字段。对吧,内部知道。那当然有可能没有是吧,如果没有怎么办呢?如果没有就去看,就去看这个B。中。嵌入的啊中。中嵌入的。嵌入什么呢?这个呃,匿名结构体,匿名结构体。那你这个B现在是不是有有嵌入,是不是嵌入一个匿密结构体叫A呀,是吧,那嵌入结构体A中有没有A。有没有?有没有这个。有没有定义啊,有没有这个声明或者叫定义都可以声明这个name字段,如果有就调用。如果有就调用。就掉。就调用对吧,如果有就调用,如果没有,如果没有,那么就看这个A里面还有没有嵌入,就如果A里面它还有嵌入结构体,它就依次向上找,如果没有继续继续查找。
11:13
继续继续往上走。继续查找啊,继续查找,如果都找不到,如果都找不到,如果不停的找都找不到,如果都找了一圈都找不到,找不到就报错了,就报错。明白的意思吧,比如说打个比方,我们这个A里边,它的的确确有一个name,如果你把这个name去掉。对,如果你把这个类目去掉,肯定要报错的啊,肯定要报错,当然了,如果你这个A里面又出现了一个应力结构体C。好。那那怎么办呢?你看啊,这个这个叫不停往上找嘛,就是如果你这个他在他现在。他这个B他自己找一下有没有,没有的话,他找这个秘密结构体A有没有A,如果没有他在找这个C,当然你前提是这确实有这个C啊,如果没有的话,那当然他就相当于找到头了,那找到头还没找到就报错,如果这有C的话,继续往上继续找,意思类推。
12:10
明白了,所以这块呢,我就先不举例了,好吧,后面我们再讲这个继承的这个层次的时候,再提到这个观点,好,这点请大家注意啊,可以简写,这两个是可以简写,你看这个地方它就找到了吗。对不对?好,关于这个细节大家注意一下,再看一个细节,当结构体和匿名结构体有相同字段或方法的时候怎么办?这时注意听,那么编译器会采用一个叫做就近访问原则来进行这个处理,如果希望访问匿名结构体字段的时候呢,可以通过匿名结构体来进行区分。那我还给他举个例子。注意听啊,这些都是比较重要的细节。啊,不然的话,以后看别人代码你也你也看不懂,同时让自己写代码也也很费劲。好,我把这个呢案例给大家举一个,举一个,比如说现在呢,我们还以还以刚才写的这个代码为例啊为例,比如说我这个B里面我也有一个。
13:08
Name。我我也定了一个name。好了。我也定了,定了定义了一个name啊,注意听同时呢,我在这个呃,这个B呢,也有一个c hello的方法,我们来看下这个时候他会怎么办啊type。然后呢,我给他绑定。给B这个指针类型绑定一个c hello的方法,大家可以考虑一下啊,C hello,好,这个时候我们输出一句话。那说出一句什么话呢?我写一句话叫做B。这个类里面的say hello方法,但这个时候。你这个B里面去访问这个名字啊,就通过B去访问这个名字,我们看看会怎么样啊会怎么样。好,同学们来考虑考虑。同学们先考虑一下啊,如果我现在这样去使用。我还这样去使用,那么为了为了上面不打架的话呢,我们再重新写一下,好吧,我们重新写一下,所以现在的情况跟原先不一样了啊,就说我这个B里面也有name字段了。
14:09
我这个内字段它会不会冲突呢?它并不会冲突。它会采用就近原则,同时B这个类型呢,我也给他写了一个c hello,方法看清楚了啊,我故意名字都给他写的一样,那这个时候如果我们来定义一个变量啊,定义一个这个B这个类型,大家看清楚,我呢还像这样访问b name。等于,比如说叫做Jack。好的B。Age。等于100岁,好b.C哈。C hello OK,当然b.hello我们我们先来分析一下,这个时候它会输出什么信息,首先我们看这个地方。先问大家第一个问题,就是说这个时候b.name他去找这个name的时候,其实他在自身已经找到一个name字段了,因此他就不会给A的这个name。
15:00
复制是吧,那也就是说此时此刻这个地方是肯定不会报错的。那么这个时候呢,这个b.age因为b.age它本身没有age,于是它会找到A里面这个age,给这个A的这个age字段复制,因此呢,这个也是没有错的。背出的好,关键的问题在这里来了,那么b.C号COK,注意听b.Co OK,实际上它掉的是它,于是它会掉的是这个函数了,于是它会输出BCOK。因为你本身有这个方法,他就不往上面去找了,然后他调的是b.name注意听,如果是b.name的话,是不是他就找到自己这个name,而你这个name是不是刚好就是刚才附的Jack啊。所以他就输出这句话,OK c OK Jackie,然后hello呢?大家想想这个c hello b.hello b.hello其实掉的是他。是不是他?
16:00
那在交叉的时候呢,这个地方他肯定会把这个AK输出来。因为它有关键是这大家看。A点内到底。会输出什么?因为这个时候他。他这个地方是用B掉进去的,而你这调的是a.name那这个地方到底是输出J还是一个空串呢?问题在这。好,这个是输出Jack。还是还是空算来我们来分析一把,那最近啊,这个地方是个细节,来,我们先运行一下,看一下跟我们分析有没有OK,就说这个地方结果肯定是正确的,关键是这A。Hello go,输出输出的Jack还是空串,为什么是空串?因为如果你真的找的是这个啊,找的是这个A点内,那肯定是空串,我看这报的是什么错。不期望after top。
17:04
不期望的是吧。好,我们看一下这个地方的问题啊。来大家看一下这个问题是在哪里,是不是这写错了是吧,写个function才对,对吧?好这个保存就可以来我们来运行一下,同学们,我们来运行一下看这个效果。来跑一个代码。走。我们运行过后,我们发现,诶大家看第一个跟我们分析是完全一样的是bc OK Jackie后面a hello空串,也就是说这个地方注意同学,注意同学们他在调B点哈的时候,其实真的就是调的这个hello,而你这地方写的就是A点内,那么他就会去找哪个呢?就会去找这个A。这个结构体面内蒙,当然这个内蒙其实你是没有给他赋,没给他赋任何值的,因为你给这个地方你写的很清楚,就是诶这个类型就是它说以他调的就是这个这个你嵌入的这个匿名结构体里边的这个A的实例的这个name,但是你没给它赋值。
18:11
你并没有给他复制,因此呢,实际上这个方就输出这个空制五串能理解吧,那当然有些同学老师我就要给他复制,怎么办呢?可以这样写,如果你一定要给A的name赋值,那你就通过匿名来做,因为大家看你b.name等于JK好,给的是b name里面字段负的JK,你b.a点内好,这个就肯定是给谁负的值。肯定就是给你的这个匿名结构体,这个实例的name字段复值,你比如说我给他起一个名字叫做SC,这个时候他肯定输出的是SC了。明白这意思吧,他这是说的是SC来我们再跑一下,看看老师分析的对不对,我们跑一下,我们发现,诶的确。是不是,是不是Scott。
19:00
是一个SC的吧,完全正确,完全正确,好,这里呢,我们就把它总结一下这个规则了,同学们看啊,这个规则是怎么样的呢?大家看这里,当结构体和匿名结构体相同字段时,编译器会采用就近原则来进行访问,如果希望访问匿名结构体和字段,访问到匿名结构体的字段和方法怎么办?通过匿名结构体名字来区分,比如说刚才老师写的这个东西。对吧,同样我们方法也可以做做,比如说周老师,我就想去访问A里面的c hello,那你这样写就可以了。这样肯定就没问题。对不对,为什么?因为你明确告诉他了,说我要访问A里面的c hello,那这个时候输出的是什么呢?那这个时候输的就是A。嘻哈。是不是输出这个AC hello,同时这里面是不是要把这个a name也输出来,但是a name是不是你已经给值了,A是不是输出SC,因此呢,这个地方输入是AC hello Scott。
20:06
明白意思吧,来,我们跑一下。我们跑一下,看看结果是不是这样子的,同学们看结果我们分析的是正确的AC hello,里面有个SCOK。好同学们,那关于这个细节呢,我们就给大家分析到这里,我把这个板述一下啊,板述一下。好,这块板书呢,我就直接把这个拿过来用一下就行了,这已经写的很清楚了,好吧,写的很清楚,这是我们讲解的继承深入讨论的第一部分啊,第一部分大家看一下有三个三个地方啊,第一个。就是我们结构体可以可以访问嵌套匿名结构体所有的字段和方法,不管你是首字母大写还是小写,这是需要注意的第一点。好,把这个往上拿一点吧。好拿一点这样子。可以节省的空间。
21:00
再往这边再挪一下。不需要这么大对吧,不需要这么大。这是第一点啊,刚才说的这个关于访问的这个这个大小写的问题,第二个匿名结构体可以简化,简化的时候呢,要注意就是这两个啊,这两个但是在简化的,大家要知道他在访问的时候,它的原则是什么,它是采用这个就近原则,也就说它的这个逻辑,大家看我这里写的,当我们直接通过B访问字段和方法时,其执行流程如下。要把它搞清楚,他怎么做的呢?他还是先到这个B里面去找有没有,如果有我就直接访问,如果没有,我往结匿名结构体里面去找,如果匿名结构体还没有,再找上一级的匿名结构体,如果都找不到报错。好,第三点就是如果我们结构体,我们自己的结构体和匿名结构体有相同的字段和方法是怎么办?那么编译器它会默认采用就近原则。如果你就是想访问匿名结构体字段和方法怎么办?你通过这个匿名结构体的名,匿名结构体的这个名字来区分,比如说b.a点内等等这种方式啊好,关于第一部分细节,我们就先给大家介绍到这里。
我来说两句