00:01
各位,我们接着来看一下方法的调用和传承机制,这一点呢很重要啊,这点很重要,就说就说我们来看一下方法的调用和传承机制呢,它它首先说这个跟函数其实是很相似的,但是不一样的地方呢,也有不一样的地方是哪里呢?就是方法调用时。方法调用时,会将调用方法的这个变量。就是谁调用这个方法,它不是有个变量来调用的吗?他会把这个变量也当做时差传给方传,传递给方法,那下面呢,我们举例来说明一下,那为了把这个东西讲清楚说明白呢,我们还是通过以前的老规矩画图。好吧,我们来画一下get,前面讲画出前面get上方法的执行过程,把这个执行过程画出来,过后呢,我们再加一个说明,大家就对方法调用和传承机制有一个比较明确的认识了。好吧,来,我们把这个呢给大家整理一下,我们来说一说。
01:05
方法的调用和传承机制是怎么一回事?来走一个,先给大家一个标题三,没问题吧,好,我们来走一走。好,我们来看看第一个案例,画出它对应的这个示意图。好,在这里稍微稍微的把它板述一下,说明这个是案例对不对。板书一下。那么我们来画出这个get sum方法的执行过程,那前面呢,我们在举例的时候,大家看是不是我们写过一个get sum,然后这里传了一个十和20,然后他返回一个结果对吧?那为了把这个东西说清楚一点呢,说的更明白一点,我这样子啊,我这样子用这个变量来传。比如说这定了一个N10。11等于十对吧。这样子用类型推导,然后N2。
02:04
N2。N2N2这个值呢,给他一个20。然后这个地方传的时候,我们直接用变量传。这样待会儿呢,我再讲的时候就更容易把它说清楚了,好结果我们先来看看此时此刻运行的结果呢,仍然是一样的,还是result等于30,没问题吧,大家看。它仍然是等于30。还是等于三四好,我们来看看这段代码它是怎么执行的,首先呢,把这一段代码放到我们的Excel文件。这块。把它拿过来。好,拿过来。好,然后get sum这个函数,我们也把它拿过来,呃,方法我们也拿过来。盖上他这个方法我们也拿过来。
03:00
这样呢,有一个对比就。比较容易讲解好,我把它放好啊。放好了。那放好我们代码呢,就开始执行了,执行的时候我们画出对应的内存图。我们画出对应的内存图。好,假设这是我们的内存。稍微的把它放大一点。这是内存。好,那那现在呢,我们就来说这个代码了,首先第一句他先执行了哪里他先执行的N1好,大家都知道这一段代码,就是现在老师选中这这段代码呢,它是属于main函数的,对不对,那这样子的话呢,Main这个函数呢,它有自己独立的一个数据空间。我们把它叫做命战。好,这里呢,有个命。面战。
04:00
好,估计这么写啊,里面呢,有一个N1这个变量了,对吧,N1是个基本数据类型,N1呢,它指向一个空间啊,这个空间我就简写了,就叫十。紧接着呢,他又执行了下面这句话,叫N2,那N2我们可以看到。对吧,同学们,它呢又指向一个数据空间,这个空间呢,对不对,叫20没吧。好,紧接着呢,它在这里去调用了,调用了P一点该上,注意,嗯,调用p.get上,大家知道它是先执行这边先执行这一个的类型推导符右面的代码,也就是说p.get sum,当它执行p.get sum的时候呢,根据我们前面讲的原则,它会生成一个新的独立的数据空间,我们姑且把它叫做什么呢?Get sum上。以前是不是讲过这个原理啊,它还是一样的,当他当他调用这个站的时候呢,它会把N1和N2传给。
05:04
这个get sum这个方法的N1和N2,那么它会进行一个只拷贝,因此在这个站里边也会有个N1,它的值为10N,同时它还会有一个变量叫N2,它的值为20,因为它满足我们这个只拷贝的原则。好,此时此刻注意听。P在哦,这面我们再说一遍啊呃,在在主函数调用之前,这个P是不是已经存在了。是吧,你P肯定已经存在,好P我们也把它画出来。忘画了啊,P它是指向一个什么?P是不是一个结构体啊,同学们。P是不是一个结构体,是一个person,它里面有一个字段叫name,好,我们也把这个P画出来,P呢,它是指向一个结构体的,这个结构体里面有一个字段叫name name里面有个值。汤姆,对吧,这是它的一个字段name没问题吧,这样看没问题吧,好,那注意这个关键点啊,当它p.get上的时候,除了把刚才的P1N1和N2进行一个自拷贝之外呢,同时他会也会把这个。
06:16
主函数里面的P也当做一个参数传给这边这个P,那也就是说在get sum这个站里面,其实也有一份相同的数据类型啊,相同的P。但是他们其实是独立的数据空间,也就是说也有也有这么一个P。这一点就是跟函数调用不一样的,因为P在调用get上的时候,它本身这个P这个变量也会当做一份,也会当做一个行参传给这个P,这个P呢,接收过后呢,他也会在这个这个站里边也会生成一个相同的一个拷贝。拷贝,因为大家都知道P呢,嗯,它是结构体,结构体是只拷贝能理解吧,所以说当他传过来的时候,其实在这个干上站里边也有一个P这个结构体,它的数据也是汤姆。
07:12
它有个字段叫内好,紧接着他执行的一个,呃,N1加N2,好,同学们,N1加N2过后呢,他这执行的一句话。他这没有没有用变量啊,他直接执行了一句话,他执行了一句什么话呢?同学们,他执行了一个return。就是N1加N2,那N1加N2是不是就是十加20,于是这个呢,就返回这个30,这个30会返给谁,注意听。这个30会返给谁呢?他把这个值就返回了,返回给这个值了,因为你这一程不就回来了吗?相当于这个地方就是老师现在选中的这个位置。这个位置我把它标成一个红色的线,这个位置呢,会变成一个30。明白吧,也就是说相当于在我们主站里边呢,会有这么一句话叫re。
08:06
多少呢?30就来了。因为你这执行完了过后,你不是把这个值返回给他了吗?那这一段这个p.get sum就变成就相当于说你你相当于说把它理解成这个红色的,红色的这个部分就变成一个30了,红色的笑话也变成30,等于相当于变成这个东西了。明白吗?好,最后你这往下继续走,输出RS等于什么什么,那么在我们的什么呢?在我们的这一个控制台。终端啊,那叫终端。这个终端呢,它就会输出一句话叫res result等于多少呢?等于30,好,这就是大家看到这个30是怎么来的。看到没有,非常的简单啊,就这么一回事,这就是我们的第一个get sum,它整个执行的一个流程,这地方大家一定要非常清楚的知道啊,就是在调用方法的时候,其实它也是在不停的进行这个拷贝,那么如果你是值,如果你是值类型,那就相当于说把这个值就拷贝了一份过去,当然大家想如果我们我们不是值类型,而是一个引用类型的话,那大家可以想象,那这个时候呢,拷贝的过来就是这个地方相当于是个地值了。
09:22
因为我这块是值,因此我就画的是值,明白啊好,这是我们第一个题的一个内存分析。好,我把它呢,先整理到这块。好,我对他做一个简单的说明,我对他做一个简单说明。我们说明一下上面的代码说明啊。第一点呢,我们可以看到在方法调用的时候,它的机制和函数是一样的。在通过一个变量去调用,调用它绑定的它通过一个变量去调用的方法时,方法时其机制其调用机制。
10:06
和什么呢?和这个函数几乎是一样的函数一样。对吧,它是和函数一样吗?没问题。一样。这是第一句话,第二句话呢,就是不一样的地方就是什么呀,就是呃,这个调用方法的这个变量也会作为一个形参传递给传递到方法里边去啊,不一样的就是什么,不一样的地方是。不一样的地方是什么呢?就是变量调用。调用。调用方法时。本身该变量本身,该变量本身。本身也会也会作为作为一个参数啊,传递到传递到哪里去呢?传递到方法中。哎,传授方法中,那这个时候呢,就要看你这个变量是什么类型的,如果你变量是指类型,那就是只拷贝,如果变量是引用类型,那就是我们的地址拷贝,明白这点啊,那这边要看如果如果变量是值类型。
11:15
职内。类型啊,则则进行只拷贝。拷贝,那如果如果变量是引用类型。引用类型则进行进行什么呢?地址拷贝。地址。这个地址拷贝。OK。拷贝啊,OK,这点大家请注意这个上面这个图就已经说的非常清楚了,好,为了加深大家认识呢,我们再举第二个案例。因为一个案例呢,有时候可能大家还没有把它彻底的认识清楚,我们再举一个案例,这个案例呢,我这也写清楚,大家看一下他是这么要求的。
12:01
他说,请编写一个程序,好,我把它整体先拿到这里来吧。他说请编写一个程序,要求如下,第一步,先声明。他说先要声明一个结构体。好,这个结构体呢叫circle,圆的意思字段为reduce,半径就是圆总是有半径的嘛,这是第一句话,第二句话呢,Reduce。第二个声明一个方法叫error和circle进行绑定,并可以返回面积,就是把这个面积呢可以返回来。好,这是第三个提示,画出我们L执行的过程加说明,好,我们就针对这个要求来完成相应的代码走一个。嗯,那这块呢,我们最好是新建一个文件夹,不要再继续在这写了啊。我们这地方叫做方法的练习。Method。
13:02
RC对吧,好,我们新建一个main函数啊,命命命命顶构。抛弃了。我们把这个代码先粘过来,好吧,这是我们的要求。那把前面这一部分共用的部分呢,我们把它拿过来用一下。好,写一个主函数。好,写完,那我们先来看一下这个具体要求,我们就一步一步的做,做完了过后呢,我们画图,好吧,我们画图。把它整体注销,像啊注销。好,第一步他要建一个结构体,叫circle,字段为reduce,这个很简单,Type。我把这个circle粘一下。Circle,然后呢是一个结构体刷,他说这里面有一个变量叫做radious,那radious放进去,Radio呢,肯定是一个小数了,就半径嘛,对吧,写完了。
14:01
好,同时呢,他说第二步,第二步要声明一个方法和他进行绑定好,这个呢也没有难度,我们一起做,那既然是个方法啊方法我们就function。那前面他说是跟circle绑定的,因此呢,我们前面来做一个C,简单这样写好吧,然后呢,名字叫error。EA。嗯,有参数吗?没有,他没有说要传什么参数进去,那就不写了,但是他要返回一个面积,面积呢,我们仍然叫FLOAT64啊,类型是FLOAT64。好,那这个时候面积怎么计算呢?好面积其实很好计算,就是你这个圆的什么呀,你这个圆的直径,那你的这个圆的半径。派R平方嘛,对吧,派R平方那就是派,那把这个派先写出来啊,派先取出来3.14吧,3.14乘以它的这个半径就是c.reduce。
15:01
乘以再乘以一次乘两次c.RA ad us写完了reduce,好,整个这个结果就写完,那写完过后呢,调用它一下调用,那调用之前我们是不是首先要创建一个结构体是吧?先创建。创建一个circle这样的结构体变量。好,这个很简单,我们VR。C。对不对,然后呢,给他一个指定一个这个半径,Reduce等于多少呢?比如说我指定4.0。没问题吧,指定4.0,然后呢,我计算它一下,因为它有返回值,我就接受了啊,那这个面积比叫res等于C点什么呀?Error。写进去。写进去过后呢,这个地方它就会返回一个结果,我把这个结果打印出来。PN。好吧,那这个时候我们打印出这个面积是,面积是多少呢?输出。
16:05
那就是RS,我们执行下这段代码。CDDR啊CD点点上一节。我们进入到他的这个位置,那么就是我们刚才的Excel。My said said。对吧。好,进到这里,Go run一下,命点go。跑起来我们看效果,我们看到这个时候结果呢,跟我们想的是一样的,50.24正确,那现在的重点就是要给大家分析一下这里面这个过程是怎么样做的,他的这个流程是怎么样子的,来我们还是老规矩,这次呢我们稍微画快一点。好,把这段代码先拿过来。好,我们一起来分析一下。他这个地方呢,跟前面其实是非常非常相似,对不对,好,我们来一起走一下,首先代码从这里开始走。
17:03
对吧。他创建了一个circle结构体哈,如果创建一个circle结构体的话,在我们内存里面它是这样子的。好,这是我们的内存。这是我们的一块内存,那首先呢,他怎么做呢?好的,他这样子的假设这是我们的主站。就是我们的幂函数。这个main函数里边呢,诶,我们先写到main。并站。对吧,面在里面有一个CC就创建好了C它是一个结构体,它指向一个结构体,结构体里面有一个,呃往下走,它给它附了一个值,好结构体里面呢,有一个字段叫什么呀,叫reduce。吃这个reduce reduce。然后里面给了多少呢?他给了一个是4.0。没问题,对不对,好,紧接着呢,它在这里调用它,那就是c.LCDL,根据我们以前讲的规则,它会创建一个新的独立的数据空间,那么这个空间呢,我们把它叫做勾线,叫做AR战吧。
18:07
好,这个站里面呢,他也会把它相当于说把这份。把要把他自己也复制过来好,他刚开始的时候是没有的啊,没有的话,因为他在传的时候这个C。这个变量本身也会传到这个地方来,于是在A这个站里边呢,也有一份相同的这么一个。相同的这么一个结构体。那就这样一个情况。好进到这里面呢,它就执行一个运算,它运算怎么运算呢?它运算的结果是3.14。去乘以乘以谁乘以C点。这个。S,那同学们注意这个时候这个c.radiOS它是它是从这里面取的啊,注意。他是从这里面取的。并不是从这个里面取的,明白吗?虽然值都一样,但是大家一定要搞清楚它是从哪取的,千万不要认为是从这取啊,它是从error这个站里面的这个这个C变量取出来的,那也就是说相当于是4.0。
19:10
再乘以一个4.0完事,那整个这个结果运算完了过后它就return了,大家看它下面不是整个是个return吗。好,瑞到哪里去了呢?各位同学,他瑞到这个地方来了,这不是有个res接收了吗?对吧,相当于说这个地方,它会把这个值计算出来过后返回过来,返回过来,那这个值等于多少呢?我们可以算一下,这个值其实就是等于同学们看到的50.40。五十点二十,那也就是说这个地方就得到了五十点二十。那具体来说就相当于是这个结果从哪返回来了,从这返回他这个结果一拿到这个return,他就到这来了。返回到这个位置能理解吧,返回到这个位置,当然当他把这个值返回到这来过后呢,你下面有一句话叫fmt输出。
20:03
对吧,你输出什么呀,你输出这个面积等于多少面积,面积是多少多少啊,那这个时候在我们的控制台注意听。这是假设这个地方是我们的控制台。对吧,这是我们的终端吧,终端。这个终端呢,就会输出这句话就是面积。啊,就是这句话。说白了,就这句话。是不是就这句话,那那我把它粘过来吧。全选一下。是不是就返回了这句话?我把它说到这了。就这么回事,当然当他当他这个返回了过后,其实上面这个空间就销毁了。没有了吧,当然等到他把这句话啊,等到这个主函数把这句话输出过后呢,他自己也就执行完毕,连这个也就没有了,那这个内存就全部释放了,能理解吧,好,那我把它撤回去啊,为了大家能够看到,我把它撤回去。好,撤回去。
21:00
大家看这个情况好不好,这个就是我们针对又一个方法调用的一个完整的案例说明,大家一定要认真听,这个大家看起来是很简单,当我们做一个项目的时候,如果这个细节就是这个本质没有搞清楚,你不是很确定的情况下,你就会产生各种歧义,那么你再去看别人项目的时候呢,你就拿不定主意了,所以说我们经常去跟学员交流的时候,我们会发现学生往往。就是学学生为什么这个东西他没有听懂,没有学明白呢?其实就是那些比较重要的一些基础和本质的东西没有搞清楚,你看我没有讲这个东西的时候,可能很多同学认为这个C,这个C就是这个C,他认为这个C这个C是同一个,那就麻烦了。那就麻烦了,当然它它可不可以变成同一个呢?也可以,如果你把这个circle这个类型改成是个指针,诶,它也一样可以。把这个东西通过这个地址去引用到你这个命站里面的这个circle也是可能的,也是可以的,对不对,但是呢,这个地方他没有用指针,因此呢,同学们他就会进行一个什么呀指拷贝,显然这种效率呢会比较低下,因此呢,后边我们就会去讲,在更多的情况下,在更多的情况下,其实我们会把这个地方改成什么呢?改成它。
22:24
那当然你改成它过后,同学们看,当我一保存,你看当我已保存过,你会发现这个值,这个变量没有变错,为什么C点这个地方是不是还是可以,还是可以访问呢?以前我们讲过这个。指针它为什么可以访问,其实本质上它这个标准写法应该变成C这样写。因为它是一个指针嘛,你先应该把这个结构体找到再去用,但是呢,它底层里面做了一个优化,说这样写也可以,好,我们来仔细看,你这样写就可以也可以。那他结果还是五十点二十。但是大家要注意,当你这加了一个星号的时候呢,整个这个内存图画就不一样了,它就不是这个地方,这个C,它就指向的不是一个具体的一个reduce,而是一个指针,它这个地方就会指向谁呢?指向这个C,这个C的一个指针,后面我们再说,也就是说这方存的是个地址了。
23:16
这个虫子是个地址。对不对,这个地址指向谁呢?指向。这个这个结构题明白吧,他就不会再有个只拷贝了,这个呢,我们在后面还会继续说好吧,大家这先提一嘴,先提一嘴好的,那关于这个。就是案例二的他的一个示意图,还有他执行的流程的分析,我们就给大家讲到这里,大家看理解了没有,很重要啊,很重要OK。那同学们,我把这段代码呢,也给大家整理到我们的板书,到我们的笔记里边去,大家以后有个印象。好,同学们,那关于我们这一个就是方法调用和传承的机制呢,我们就给大家介绍完了,大家领会一下。
我来说两句