继承
继承的基本语法
class 子类 extands 父类 { }
父类也叫超类,基类 子类也叫派生类
子类继承了所有的属性和方法,非私有的属性和方法可以在子类直接访问,但是私有属性和方法不能在子类直接访问,要通过父类提供的公共的方法去访问
子类必须调用父类的构造器,完成父类的初始化才能共享父类的属性和方法,因为构造器不能继承,子类构造器都会有一个默认的super()方法来初始化父类
当创建子类对象时,不管使用子类的哪个构造器,默认情况下总会先去调用父类的无参构造器
如果父类没有提供无参构造器,则必须在子类的每一个构造器中用super去指定父类的哪个构造器完成对父类的初始化工作,否则编译器不会通过 (韩顺平第289集,不懂多听几遍)
所有构造器如果没有显式声明那么在最前面一定默认有一个调用父类无参构造器的super()
package com.lwhxx.extend.improve_; //这是父类 public class Base { public int n1=100; protected int n2=200; int n3=300; private int n4=400; public Base(){ //无参构造器 System.out.println("父类Base()构造器被调用...."); } public Base(String name,int age){ System.out.println("父类Base(String name,int age)被调用"); } public int getN4(){ //父类提供了一个公共方法,子类可以访问父类的n4 return n4; } public void test100(){ System.out.println("test100"); } protected void test200(){ System.out.println("test200"); } void test300(){ System.out.println("test300"); } private void test400(){ System.out.println("test400"); } public void callTest400(){ //call调用的意思,和上面getn4相似,子类不能直接调,得写一个公共的类让它帮我们调 test400(); } }
package com.lwhxx.extend.improve_; //这是子类 public class Sub extends Base { public Sub() { // 子类构造器 super("lili", 20); //有super(),先调用父类的含参构造器 System.out.println("子类Sub()构造器被调用....."); } public Sub(String name){ super("tom",30); //有super(),先调用父类的含参构造器 System.out.println("子类Sub(String name)被调用"); } public void sayok() { //子类方法 System.out.println(n1 + " " + n2 + " " + n3); test100(); test200(); test300(); System.out.println(getN4()); callTest400(); //调用父类的私有方法 }
package com.lwhxx.extend.improve_; //这是主函数(测试函数)
public class ExtendsDetail {
public static void main(String[] args) {
Sub sub = new Sub(); //创建了子类对象 sub
System.out.println("==第二个对象==");
Sub jack = new Sub("jack"); //创建了第二个子类对象
// sub.sayok();
}
}
super()使用时必须放在构造器第一行
super()和this()都只能放在构造器的第一行,因此两个方法不能共存在同一个构造器 this.方法名和this()不一样,但super()能和this.属性名共存
Object类是所有类的基类(父类) ctrl h可以查看
父类构造器的调用不限于父类,将一向上追溯至Object类(顶级父类)
java只能继承一个父类,单继承机制 不能滥用继承,子类和父类必须满足is-a的逻辑关系
继承本质分析(重要)
package com.lwhxx.extend.improve_;
/*
讲解继承的本质 继承的查找关系
*/
public class ExtendThory {
public static void main(String[] args) {
Son son = new Son();
System.out.println(son.name); //先查子类,找不到往上找,直至Object,输出的是大头儿子
System.out.println(son.age); //儿子查找不到age,往上查父亲,查到了输出39
System.out.println(son.hobby);//儿子和父亲都查找不到hobby,就查找爷爷输出旅行
}
}
class GrandPa{
String name="大头爷爷";
String hobby="旅游";
}
class Father extends GrandPa{
String name="大头爸爸";
int age=39;
}
class Son extends Father{
String name="大头儿子";
}
查找关系:如果子类有这个属性,并且可以访问,则返回信息,没有就看父类以此类推直至Object,如果儿子的年龄存在但不能访问而爸爸的年龄存在而且能访问,那么son.age也不会跳过儿子访问爸爸而是会报错
super关键字
super代表父类的引用,用于访问父类的属性,方法,构造器
访问父类的属性,但不能访问父类的private方法
访问父类的方法,不能访问父类的private方法
访问父类的构造器 super(参数列表)只能放在构造器的第一句,只能出现一句!
方法重写/覆盖
定义: 子类的一个方法和父类的某个方法的名称,返回类型,参数一样,那么我们就说子类的这个方法覆盖了父类方法
子类的返回类型和父类返回类型要一样或者是父类返回类型的子类型 比如父类返回类型是Object,而子类是String时就可以
子类方法不能缩小父类方法的访问权限 public>protected>默认>private
比较方法的重载和重写(从发生范围,方法名要求,形参列表,返回类型,修饰符五个角度比较)