继承是面向对象程序设计的一个重要特性。在现有类的基础上建立新类的处理过程称为继承。由继承而得来的类称为子类,被继承的类称为父类。直接或者间接被继承的类都是父类。子类继承父类的状态和行为,同时也可以修改父类的状态和重写父类的方法,并添加新的状态和行为。
Java中的继承是通过extends关键字来实现的
class B extends A{ ... }
B为A的直接子类,如果A又是另外某个类的子类,那么B同时也是A的间接子类。子类可以继承父类中访问权限设定为public,protected,default的成员属性和成员方法,但是不能继承访问权限为private的成员属性和成员方法,且父类的构造方法不能被继承。
Java中的方法重写(override)是指子类重写父类的方法。子类可以改写父类方法所实现的功能,但是子类重写的方法必须与父类中对应的方法具有相同的方法名,返回值类型和参数列表。
所以说方法重写是只是方法的具体实现有所区别。
Java中的方法重写应该注意一下规则:
(1)子类重写方法的名称,返回值类型与参数列表必须与父类被重写的方法一致
(2)子类中重写方法的访问权限不能缩小,例如父类中方法权限是public,子类中只能是public;父类中方法权限是protected,子类中只能是public或者protected;父类中方法权限是默认权限,子类中只能是public或者protected或者默认权限;父类中的私有方法不能被子类继承。
(3)子类重写方法中不能抛出新的异常
方法重写使得Java支持多态,这是面向对象的三大特点(封装,继承,多态)之一
super是当前对象里面的父对象的引用(达到可访问权限,除了private)。Java中通过super关键字来实现对父类中被重写方法的调用。
运用super可以调用父类的成员方法,构造方法和成员属性。
(1)调用父类的成员方法:super.method([paramlist])
(2)调用父类的构造方法:super.([paramlist])
(3)调用父类的成员属性:super.filed
class Student { public int age; public void std(){ //声明Student类的方法std() age = 15; System.out.println("学生平均年龄为:"+age); } } class ThisStudent extends Student{ public int age; public void std(){ super.std(); //使用super作为父类对象的引用对象来调用父类对象里面的Std()方法 age = 18; System.out.println("这个学生的年龄为:"+age); System.out.println(super.age); //使用super作为父类对象的引用对象来调用父类对象中的age值 System.out.println(age); } } public class TestDif { public static void main(String[] args) { ThisStudent a = new ThisStudent(); a.std(); } } /** 学生平均年龄为:15 这个学生的年龄为:18 15 18 */
当子类调用一个由父类定义的构造方法时,super语句必须是子类构造方法中第一条被执行的语句。如果子类的构造方法中没有执行super()语句,该构造方法中还是会隐式的使用super()来调用父类中默认的构造方法,并且这条语句在子类的构造方法中都是第一个被执行。
调用父类构造方法的super关键字用法
package Liu; class Mamal{ public Mamal() { //默认构造方法 System.out.println("我是哺乳动物."); } public Mamal(int legs) { //带参数构造方法 System.out.println("我是一只" + legs + "的哺乳动物."); } } class Cat extends Mamal{ public Cat() { //super(); //这一句写不写都会被执行 System.out.println("我是一只猫."); } } class Sheep extends Mamal{ public Sheep() { super(4); //调用父类的带参数构造方法 System.out.println("我是一只羊."); } } //测试类 public class TextSuper { public static void main(String[] args) { // TODO Auto-generated method stub Cat cat = new Cat(); Sheep dog = new Sheep(); } } /** 我是哺乳动物. 我是一只猫. 我是一只4的哺乳动物. 我是一只羊. */
如果一个父类没有默认构造方法呢?那么子类不能使用父类的默认构造方法。
会报错:The constructor Mamal() is undefined
那要是在父类没有默认构造方法的情况下子类写默认构造方法呢?
class Cat extends Mamal{ public Cat() { System.out.println("我是一只"+ x + "猫."); } }
会报错:Implicit super constructor Mamal() is undefined. Must explicitly invoke another constructor
class Sheep extends Mamal{ public Sheep() { super(4); //调用父类的带参数构造方法 System.out.println("我是一只羊."); } }
这个不会报错,分析得:如果父类没有默认构造方法,子类在写构造方法时必须继承父类的其他带参数的构造方法,第一句要写super([paramlist]);
为了方便编程,在创建父类的时候最好写出默认构造方法,哪怕是空语句也行
public Mamal() { ... }
这样给子类写构造函数的时候就不会有这么多烦恼了!
使用super调用父类中的成员方法
package Liu; class Mamal{ public void call() { System.out.println("哺乳动物会叫"); } } class Sheep extends Mamal{ public void call() { super.call();//调用父类的call()方法 System.out.println("羊会咩咩叫"); } } //测试类 public class TestSuper2 { public static void main(String[] args) { // TODO Auto-generated method stub Sheep sheep = new Sheep(); sheep.call(); } } /** 哺乳动物会叫 羊会咩咩叫 */
在子类中,父类中的方法需要通过super关键字进行调用,同时也可以调用父类中被子类隐藏的属性。