课时64:属性覆盖
摘要:今天我分享的是Java中属性覆盖及super与this的区别。主要分为以三下部分。
1. 属性覆盖示例
2. 封装对属性覆盖的影响
3. super与this的区别
01. 属性覆盖示例
我们来聊聊属性覆盖,打个比方,现在有这样一个程序。先不考虑封装的事儿,我们定义一个变量 info ,比如写成 m23 这样,接着定义一个 String 类型的 Info ,赋值为 Hello world 。到这儿能明白吧?此时我们定义了两个同名的 Info 。然后如果我们用 System.out.print 输出 this.info ,访问的应该就是Hello world 。我们把代码编译一下,再执行看看, m23 的结果出来了,这就算是属性覆盖了。
class Channel { string info= "www.mldn.cn" ; } class DatabaseChannel extends Channel { //要进行数据库连接 string info= "HelloMLDN"; // 名称相同 public void fun() { System.out.println(this.infol); } } public class JavaDemo { public static void main(String args[]){ DatabaseChannel channel = new DatabaseChannel(); channel.fun() ; } }
02. 封装对属性覆盖的影响
那要是我想访问父类的那个 info 呢?很简单,加个 super 就行。编译运行一下,这个过程不难理解吧。不过我想问大家一个很直接的问题,在做属性覆盖的时候,有个前提是没有封装。那要是属性封装了会怎么样呢?一旦属性被封装, super 就不能用了。这时候我们再编译、执行代码,得到的就只能是子类的 hello world 。
再深入分析一下,假如我们在这儿写一个 GetInfo 方法,直接返回 This.info 。这个时候,如果通过 Super.getInfo 来获取,那得到的是父类的 Info 还是子类的 Info 呢?我们编译执行看看,结果得到的是父类的 Info 。
Class Channel { private string info = "www.mldn.cn" ; public string getInfo() { return this.info ; } } class DatabaseChannel extends Channel { //要进行数据库连接 String info="HelloMLDN" ; // 名称相同 public void fun() { System.out.println(this.info); System.out.println(super.getInfo()) ; } public class JavaDemo { public static void main(String args[]) { DatabaseChannel channel = new DatabaseChannel(); channel.fun () ; }
为什么呢?这是个就近取用的过程。大家回想一下之前的程序,当属性被 Private 封装时,是不能被复写的。实际上,子类和父类的私有属性没什么关系,就算名称一样,也相当于子类定义了一个新属性。所以从本质上讲,属性覆盖没太大实际意义,因为属性一旦封装,覆盖就没意义了。
03. super与this的区别
不过,这里引出了一道面试题:请解释 Super 和 This 的区别。解释的时候要清楚这几点:
在程序里,使用 This 时,会先在本类查找需要的属性或方法。要是本类没有,就查找父类定义。而使用 Super ,则是不查找本类,直接查找父类。
This 和 Super 都能调用属性,也都能调用构造方法。但 this 调用的是本类构造, Super 是由子类调用父类构造。并且这两个语句都必须放在构造方法的第一行,所以不能同时出现。
this 可以表示当前对象,而 Super 没有这种概念,从来没有父类当前对象的说法,只有本类当前对象。