继承就是字面的理解就好,子继承父的一些特性,并且还可能发生一些“基因突变”,可以包含一些父类没有的方法或者属性。正所谓“青出于蓝而胜于蓝”。
为什么要用继承呢?一方面继承可以向上抽取父类,使代码重用率提高。比如Teacher类和Student类都可以继承person类,另一方面继承可以引出多态,是面向对象的重要特性。
一个例子:
class Person { String name; Person(String name) { this.name = name; System.out.println("Person is Constructed"); } public void eat() { System.out.println("I am a person. I can eat!"); } } class Student extends Person { String num;//学号 Student(String num,String name) { //调用父类构造函数 super(name); this.num = num; System.out.println("Student is Constructed"); } public void study() { System.out.println("I am a student. I can sutdy"); } } public class InheritsTest1 { public static void main(String[] args) { //创建一个学生对象 Student student1 = new Student("zhang","111"); //调用父类的吃饭方法 student1.eat(); //调用学习方法 student1.study(); } }
要点:
1.继承的语法 class 子类 extends 父类 {}
2.子类自动拥有父类public 和protected的成员。
3.关于权限问题:
public 外界可以无限制访问
private类外不可访问,只能类内部访问
protected 继承的子类可以访问(在不同的包中也可以)
default即没写权限,默认同一包中的类可以访问。
4.super()调用父类的构造函数,这句话需要在子类构造函数中作为第一句话!!!
子类与父类中方法之间有几种关系,第一种就如上面的例子,子类直接继承父类的方法,不进行改变,可以直接调用父类的方法,子类也可以对父类的方法进行扩充,即增加新的方法。如person会eat,student继承了person类,他也会eat,但是又增加了study方法。
后两种关系都发生在子类的方法和父类重名的情况下。
1.子类覆盖父类的方法
例子:
class Person { String name; Person(String name) { this.name = name; System.out.println("Person is Constructed"); } public void eat() { System.out.println("I am a person. I can eat 饭!"); } } class Student extends Person { String num;//学号 Student(String num,String name) { //调用父类构造函数 super(name); this.num = num; System.out.println("Student is Constructed"); } public void eat() { System.out.println("I am a student .I can eat 脑白金"); } public void study() { System.out.println("I am a student. I can sutdy"); } } public class InheritsTest1 { public static void main(String[] args) { //创建一个学生对象 Student student1 = new Student("zhang","111"); //覆盖了父类的eat饭方法,调用子类的eat脑白金方法 student1.eat(); //调用学习方法 student1.study(); } }结果:
可见,子类覆盖了父类的方法。在调用子类的时候,调用eat方法,执行的不是父类的“eat饭”方法,而是子类的"eat脑白金"方法。
2.子类重载父类的方法
class Person { String name; Person(String name) { this.name = name; System.out.println("Person is Constructed"); } public void eat() { System.out.println("I am a person. I can eat 饭!"); } } class Student extends Person { String num;//学号 Student(String num,String name) { //调用父类构造函数 super(name); this.num = num; System.out.println("Student is Constructed"); } public void eat(String food) { if (food.equals("naobaijin")) System.out.println("I am a student .I can eat 脑白金"); } public void study() { System.out.println("I am a student. I can sutdy"); } } public class InheritsTest1 { public static void main(String[] args) { //创建一个学生对象 Student student1 = new Student("zhang","111"); //调用父类的eat饭方法 student1.eat(); //调用子类重载的eat脑白金方法 student1.eat("naobaijin"); //调用学习方法 student1.study(); } }
这样student既可以吃饭,也可以吃脑白金,不同就在与eat方法接受的参数不同,如果是没有参数,那么他就执行父类的eat饭方法,如果有参数,那就执行子类重载的eat脑白金方法,吃脑白金。
要点:
1.子类和父类之间的方法关系有扩充关系(直接调用父类方法或者扩充新方法),覆盖关系(子类与父类方法重名,子类方法覆盖父类方法),重载关系(子类方法与父类方法参数不同,调用时根据参数选择调用哪个方法)
2.覆盖时不能覆盖静态方法,也不能覆盖final方法。
3.覆盖方法的允许访问范围不能小于原方法,覆盖方法抛出的异常不能比原方法多。
4.在子类中可以调用父类的方法,被覆盖的也可以。即用super关键字
例子如下:
class Person1 { public void eat() { System.out.println("I am a person. I can eat 饭!"); } } class Student1 extends Person1 { public void eat() { //在子类中可以使用super关键字调用父类的方法,包括被覆盖的方法 super.eat(); System.out.println("I am a student .I can eat 脑白金"); } public void study() { System.out.println("I am a student. I can sutdy"); } } public class InheritsTest2 { public static void main(String[] args) { //创建一个学生对象 Student1 student1 = new Student1(); //调用子类的eat方法 student1.eat(); } }