文章目录
- 1.方法的覆写
- 2.类的层次结构
- 3.如何判定正确的继承顺序
- 4.如何判断子类继承(继承这个词我始终觉得很变扭)了父类的什么
- 5.继承关系的实质
- 6.关键字:super 和 this
- [1].this关键字
- (1)this关键字调用本类属性
- (2)this关键字本类方法调用
- (3)this关键字使用的注意事项
- [2].super关键字
- (1)super关键字调用父类属性
- (2)super关键字调用父类方法
- [3].super关键字和this关键字的区别
今日提要:再谈继承
1.方法的覆写
儿子遗传了爹的鼻窦炎,还有哮喘(扩展基类或者说超类的方法和实例变量),可是儿子的鼻窦炎更高级了,儿子的诊断里面就增加自己特别的鼻窦炎(覆盖基类或超类的方法),这就是子类对父类(基类或超类)的覆写,这里注意实例变量是不会被覆写,因为实例变量不定义任何特殊的行为,它们只表达状态;
这里需要注意的是,方法的覆写,只针对这个子类,子类在实例化形成对象时,可以用自己的同名方法覆写父类(基类或超类)的方法,以达到子类个性化表达的作用。
用中文是为了比较好读,代码里别用…
鸟的行动是飞行(你要非跟我抬杠,鸵鸟不能飞,你也可以在写鸵鸟这个类的时候,直接覆写鸟类的行动…)
猫是在地面奔跑的,别说爬树,说我也不理你;
鸟是吃素的,猫是吃荤的,这都是它们自己的特点,所以为它们建立自己的相关方法,覆写基类里面的相同方法,以达到依据特点实例化的目的;
方法的调用,也是遵循从具体到通用的优先级管理,也就是说,当你X.eat();//调用一个吃的方法
的时候,JVM会从最底层的类开始依次向上寻找,首先出现的就直接调用,一句话概括,JVM会选择对特定对象最特定的那个版本调用;
2.类的层次结构
用动物举例这个比较好说明,我看的资料里面都用动物,看来大家都这么认为的。好比,猫、狗、狼和老虎四个对象,我们发现猫和老虎都属于猫科,那么抽象出来的猫科就是猫和老虎的父类,而狗和狼都属于犬科,同理犬科就是狗和狼的父类,然后犬科和猫科都是动物中的一个种类,那么就可以抽象出来动物类,那么动物类就是猫科和犬科的父类,这就是类的层次结构,这个应该很好懂,但是实际上抽象的过程想当考验逻辑能力和想象力,还是有个心理准备的好;
3.如何判定正确的继承顺序
我们怎么来确定我们建立的父类,是不是某个特定子类的父类呢?方法很简单,就是问一下是不是;
比如:男老师是不是老师呢?猫是不是动物?外科医生是不是医生?等等等等,只要这个问题的答案是肯定的,那么后面的类就是前面特定类的父类,还有一点很重要必须要注意,是不是这个问题是单向的,不能反过来问,如果反过来问也出现了肯定的答案,那么这个类的继承肯定是有问题的;
4.如何判断子类继承(继承这个词我始终觉得很变扭)了父类的什么
我们说过Java有四种访问权限,从严格到宽松,依次是private<default<proteced<public;
现在我们只讨论,两种情况:如果方法被private(私有)修饰,那么成员不可继承,如果方法被public(公共)修饰,成员可以继承;
5.继承关系的实质
其实继承关系的实质就是为一组类建立了统一的一个协议,并遵循协议运行,比如Java本身;
6.关键字:super 和 this
[1].this关键字
(1)this关键字调用本类属性
- this代表当前对象(调用类中方法或属性的那个对象)的引用;
- this只能在方法内部使用;
- this.属性名:表示对象自己的属性;
来看两段代码:
代码一
public class ThisTest {private int num;private String col;ThisTest(int num,String col){num = num;col = col;}public static void main(String[] args) {ThisTest t1 = new ThisTest(20,"oo");ThisTest t2 = new ThisTest(30,"oopp");System.out.println(t1.num +" , " + t2.num);System.out.println(t1.col +" , " + t2.col);}}
输出结果:
0,0
null,null
代码二
public class ThisTest {private int num;private String col;ThisTest(int num,String col){this.num = num;this.col = col;}public static void main(String[] args) {ThisTest t1 = new ThisTest(20,"oo");ThisTest t2 = new ThisTest(30,"oopp");System.out.println(t1.num +" , " + t2.num);System.out.println(t1.col +" , " + t2.col);}}
输出结果:
20,30
oo,oopp
当构造函数参数与实例变量同名时,实例变量就被屏蔽了,它们是无法通过构造函数直接赋值的,当添加了this关键字之后,就可以被对象赋值了,而this关键字指代的是 t1 和 t2,这两个对象的引用;
来看第三段代码
public class ThisTest {private int num;private String col;ThisTest(int tempnum,String tempcol){num = tempnum;col = tempcol;}public static void main(String[] args) {ThisTest t1 = new ThisTest(20,"oo");ThisTest t2 = new ThisTest(30,"oopp");System.out.println(t1.num +" , " + t2.num);System.out.println(t1.col +" , " + t2.col);}}
输出结果:
20,30
oo,oopp
自己看不同吧,太明显了
(2)this关键字本类方法调用
- this关键字调用构造函数必须在构造函数的第一行
public class ThisTest {private int num;private String col;ThisTest(int num){ this.num = num; }ThisTest(String col){this(20);this.col = col;}public static void main(String[] args) {ThisTest t1 = new ThisTest("oo");ThisTest t2 = new ThisTest("oopp");System.out.println(t1.num +" , " + t2.num);System.out.println(t1.col +" , " + t2.col);}}
输出结果:
20 , 20
oo , oopp
重载的构造函数里面的第一行this(20)
调用的就是ThisTest(int num){......}
,必须在第一行;
- this关键字调用本类方法
public class ThisTest {void move() {System.out.println("好好学习");}void result() {this.move();System.out.println("天天向上");}public static void main(String[] args) {ThisTest s1 = new ThisTest();s1.result();}}
输出结果:
好好学习
天天向上
this.move();
调用的就是方法void move() {...}
,调用方法的时候,无所谓第几行,就看你的需要了;
(3)this关键字使用的注意事项
- this关键字只可以用于普通的实例方法;
- this关键字不可以在静态方法或静态块中使用(main()函数就是静态方法);
[2].super关键字
(1)super关键字调用父类属性
说别的啥都没啥用,看代码吧
public class SuperTest {public static void main(String[] args) {SonClass s1 = new SonClass();s1.show();}}
class SuperClass{int num = 100;
}
class SonClass extends SuperClass{int num = 10;void show () {System.out.print("爹的num= " + super.num + " , " + "儿子的num= " + num);}
}
输出结果:
爹的num= 100 , 儿子的num= 10
子类里面的super.num
调用的就是父类class SuperClass{ int num = 100;}
里面的变量num的值;
(2)super关键字调用父类方法
- super关键字调用构造函数必须在第一行;
第一段代码:
class SuperClass{int num;String col;SuperClass(){}
}
class SonClass extends SuperClass{SonClass(){super();}
}
- 子类的构造函数必须依赖父类的构造函数而建立,如果父类的构造函数为无参空函数,
super();
是默认存在的,不需要写;
第二段代码:
class SuperClass{int num;String col;SuperClass(int num,String col){}
}
class SonClass extends SuperClass{SonClass(){super(20,"oo");}
}
- 父类的构造函数含有参数的,super关键字必须依照父类构造函数的参数列表填写;
- super关键字访问父类方法;
第三段代码:
public class SuperTest {public static void main(String[] args) {SonClass s1 = new SonClass();s1.result();}}
class SuperClass{void move() {System.out.println("好好学习");}
}
class SonClass extends SuperClass{void result() {super.move();System.out.println("天天向上");}
}
输出结果:
好好学习
天天向上
这个一看就明白了,不用多说了;
[3].super关键字和this关键字的区别
这就是为什么要把这两个关键字都放在这里一起说的原因了
- super()调用父类的构造函数,必须在构造函数的第一行,this()调用本类构造函数,必须在构造函数的第一行,看到这里大家应该明白一件事情了,super()和this()不能同时调用构造函数;
- this代表调用者这个对象,super代表父类对象的引用;
- this没有继承也能使用,super必须在继承条件下;
- this()本类构造,super()父类构造;
今天的内容就写到这里了,里面太多中文要翻译成中文了,非常费劲