闭包 是可以包?span style="color: rgb(0, 0, 255);">自由Q未l定Q变?/span> 的代码块Q这些变量不是在q个代码块或者Q何全局上下文中定义的,而是在定义代码块的环境中定义?#8220;闭包” 一词来源于以下两者的l合Q要执行的代码块Q由于自由变量的存在Q相兛_量引用没有释放)和ؓ(f)自由变量提供l定的计环境(作用域)?/p>
可能上面的定义有Ҏ(gu)涩,下面看一?span style="color: rgb(0, 0, 255);">《Python 核心~程?/span> ?nbsp;闭包 的解释?/span>
如果在一个内部函数里Q对在外部作用域Q但不是在全局作用域)的变量进行引用,那么内部函数p定义?strong style="font-weight: bold;">闭包 。定义在外部函数内的但由内部函数引用或者用的变量被称?span style="color: rgb(0, 0, 255);">自由变量 ?/span>
原帖?#8220;liusong1111”回帖值得思考:(x)
Q一Q相关类
Q二Q问题:(x)以下输出l果是什么?
Q三Q答?/font>
① ?A and A
② ?A and A
③ ?A and D
④ ?B and A
⑤ ?B and A
⑥ ?A and D
⑦ ?B and B
⑧ ?B and B
⑨ ?A and D
Q四Q分?/strong>
①②③比较好理解Q一般不?x)出错。④⑤就有点p涂了,Z么输出的不是"B and B”呢Q!Q先来回一下多态性?/font>
q行时多态性是面向对象E序设计代码重用的一个最强大机制Q动态性的概念也可以被说成“一个接口,多个Ҏ(gu)”。Java实现q行时多态性的基础是动态方法调度,它是一U在q行时而不是在~译期调用重载方法的机制?/font>
Ҏ(gu)的重写Overriding和重载Overloading是Java多态性的不同表现?/font>
- 重写(Overriding) 是父cM子类之间多态性的一U表现?/font>如果在子cM定义某方法与其父cL相同的名U和参数Q我们说该方法被重写 (Overriding)。子cȝ对象使用q个Ҏ(gu)Ӟ调用子cM的定义,对它而言Q父cM的定义如同被“屏蔽”了?/font>
- 重蝲(Overloading) 是一个类中多态性的一U表现。如果在一个类中定义了多个同名的方法,它们或有不同的参C数或有不同的参数cdQ则UCؓ(f)Ҏ(gu)的重?Overloading)。Overloaded的方法是可以改变q回值的cd?/font>
当超cd象引用变量引用子cd象时Q被引用对象的类型而不是引用变量的cd军_了调用谁的成员方法,但是q个被调用的Ҏ(gu)必须是在类中定义过的,也就是说被子c覆盖的Ҏ(gu)?/em> Q但是如果强制把类转换成子cȝ话,可以调用子cM新添加而超cL有的Ҏ(gu)了。)
好了Q先温习(fn)到这里,a归正传!实际上这里涉?qing)方法调用的优先问? Q优先由高C依次为:(x)
this.show(O),
super.show(O)Q?br />
this.show((super)O),
super.show((super)O)。让我们来看看它是怎么工作的?/font>
比如④,a2.show(b)Qa2是一个引用变量,cd为AQ则this为a2Qb是B的一个实例,于是它到cA里面找show(B obj)Ҏ(gu)Q没有找刎ͼ于是到A的super(类)找,而A没有类Q因此{到第三优先this.show((super)O)Qthis仍然? a2Q这里O为BQ?super)O?super)B即AQ因此它到类A里面找show(A obj)的方法,cA有这个方法,但是׃a2引用的是cB的一个对象,B覆盖了A的show(A obj)Ҏ(gu)Q因此最l锁定到cB的show(A obj)Q输Zؓ(f)"B and A”?/font>
再比如⑧Qb.show(c)Qb是一个引用变量,cd为BQ则this为bQc是C的一个实例,于是它到cB找show(C obj)Ҏ(gu)Q没有找刎ͼ转而到B的超cA里面找,A里面也没有,因此也{到第三优先this.show((super)O)Qthis为bQO为CQ? (super)O?super)C即BQ因此它到B里面找show(B obj)Ҏ(gu)Q找CQ由于b引用的是cB的一个对象,因此直接锁定到类B的show(B obj)Q输Zؓ(f)"B and B”?/font>
按照上面的方法,可以正确得到其他的结果?/font>
问题q要l箋Q现在我们再来看上面的分析过E是怎么体现色字体那句话的内늚。它_(d)(x)当超cd象引用变量引用子cd象时Q被引用对象的类型而不是引? 变量的类型决定了调用谁的成员Ҏ(gu)Q但是这个被调用的方法必L在超cM定义q的Q也是说被子类覆盖的方法。还是拿a2.show(b)来说吧?/font>
a2是一个引用变量,cd为AQ它引用的是B的一个对象,因此q句话的意思是由B来决定调用的是哪个方法。因此应该调用B的show(B obj)从而输?B and B”才寏V但是ؓ(f)什么跟前面的分析得到的l果不相W呢Q问题在于我们不要忽略了蓝色字体的后半部分,那里特别指明Q这个被调用的方法必L在超cM定义q的Q也是被子c覆盖的Ҏ(gu)。B里面的show(B obj)在超cA中有定义吗?没有Q那更谈不上被覆盖了。实际上q句话隐藏了一条信息:(x)它仍然是按照Ҏ(gu)调用的优先来确定的。它在类A中找C show(A obj)Q如果子cB没有覆盖show(A obj)Ҏ(gu)Q那么它?yu)p用A的show(A obj)Q由于Bl承AQ虽然没有覆盖这个方法,但从类A那里l承了这个方法,从某U意义上_(d)q是由B定调用的方法,只是Ҏ(gu)是在A中实现而已Q; 现在子类B覆盖了show(A obj)Q因此它最l锁定到B的show(A obj)。这是那句话的意义所在?/font>
个hd的一Ҏ(gu)考:(x)
W?个问题值得思考,输出 a2.show(c) Q答案是 B and A
分析Q?/b>
a2是类A的引用变量,引用的是cB的一个实例对象。c是类C的一个实例?/font>
1Qthis.show(c)Q在A中找show(C obj)的方法,没有扑ֈQ进行第二步?
2Qsuper.show(c)QA没有类Q进行第三步?
3Qthis.show(super(c)), super(c)是BQA中是没有show(B obj)Ҏ(gu)的,但是q时候会(x)l箋往上找Q找B的父c,super(B)是AQ在A中找show(A obj), 扑ֈ了?
4Qa2引用的是cB的一个对象,由B来决定调用哪个方法,因ؓ(f)cB中覆盖了A的show(A obj)Ҏ(gu)Q因此最l用cB中的show(A obj)Ҏ(gu)。?/font>
所以结论是q里super(O)是采用了逐层往上寻?/b>的方式,具体来说Q父cL不到对应的showҎ(gu)Q就扄cȝ父类Q如果还没有Ql往上找Q直到找到根基类?/font>
Z验证作者原文中蓝色字体D|字的正确性,我测试了输出a1.show(c)Q结果和预想的一P是A and A.
q里Qa1.show(c)和a2.show(c)的区别在于持有的引用对象的不同,a1是持有了Acȝ一个实例对象,而a2是持有了Bcȝ一个实例对象,所以当都找CAcM?span id="_8_178_Open_Text">show(A obj)Ӟ引用的对象的cd军_了该调用哪个成员的方法,前提是这个被调用的方法必被子类覆盖了。所?/span>a1.show(c)输出的是A and AQ?a2.show(c)输出的是 B and A.