为什么要继承
会发现,狗和猫只有叫声不同,因为它们都是动物,会有相同的属性和行为,所以它们可以继承animla类
如何继承
用到extends关键字
这样就会简化好多
注意
1.Animal称为父类/超类/基类;dog,cat称为子类/派生类
2.继承父类后,必须要添加自己的成员,否则没必要继承
3.继承的作用:实现代码的复用
父类成员的访问
父类成员变量与子类不同名时
a=10;b=20;都是访问从父类继承下来的成员
c=30是访问子类自己的
父类与子类成员变量同名时
此时a=10是访问的自己的a
父类与子类成员方法同名时
总结
对父类成员的访问遵循就近原则,当父类子类的成员变量或方法同名时,就会访问子类的。
但如果成员名相同时,我就想访问父类的,该如何操作呢?
super关键字
作用:在子类中访问父类的成员
分割线上方都是Derived类内部的方法打印的,分割线下方是main方法打印的,这是因为引用a的类型是Derived,所以遵循就近原则,找到了子类中的a
注意
1.同this关键字一样,super只能在非静态方法中使用,所以在main方法中不能用到super和this
2.但是,静态的成员变量和方法也可以访问,只不过不推荐,静态的成员变量和方法一般通过类名来访问
子类构造方法
父子父子,先有父再有子,即:子类对象构造前,要先调用基类的构造方法。
我们自己没有给子类写构造方法时,编译器会默认添加上如下的构造方法
看似什么都没有,实际上这个方法的第一句是隐藏的super();这就是调用父类的构造方法,如下
当实例化son这个对象时,就会调用子类的构造方法,同时会在第一条语句执行隐藏的父类构造方法
构造方法的重载
注意看,下面的第四行代码报错了,这是为什么?
因为在父类中,我们重写了一个带参数的构造方法,所以编译器就不会默认提供不带参数的构造方法,同时,在子类的构造方法中隐藏的super()这样的调用语句就不起作用了
那如何解决?法一:在父类中写一个不带参数的构造方法。法二:在子类的构造方法中调用父类带参数的构造方法(注意,这个调用语句必须是在第一行)。如下俩种解决方案
用this在构造方法中调用其他构造方法
这个结果是什么呢?
注意,第一个被调用的子类构造方法的第一句会默认添加super(),而接下来调用的子类构造方法就不会再添加super(),因为构造方法对于一个对象只执行一次
再谈有初始化作用的代码块
没有继承关系时
静态代码块先执行,然后是实例代码块,最后是构造方法
静态代码块是在类加载时执行,不管有没有对象,不管有几个对象,只要这个类被提到了,他就执行且只执行一次
当有了对象的创建时,实例代码块才执行,最后是构造方法
有继承关系时
静态代码块优先执行,然后是父类的实例(构造方法不是静态的,也可以看作实例),最后是子类的实例
这是因为静态代码块在类加载时就执行,当编译器遇到Derived时,它会先找到父类先加载父类,然后加载子类,最后才开始创建对象,创建时还是遵循父类优先原则,先通过实例代码块和构造方法将父类中的值初始化以供子类使用,最后再对子类对象初始化。
父类中不同访问权限的成员在子类中的可见性
当父类和子类在同一个包中时
只有a是不可以被直接访问的,
当父类和子类在不同包中时
注意要用import导入父类所在的包
此时a和b都不可见,因为b是默认权限,只能在同一个包当中访问,c是可见的,因为protected修饰后,在同一个包中可以用,在不同包的子类中也可以用
final关键字
final关键字可以用来修饰变量,成员方法以及类
1.修饰变量,表示常量,不可以修改,不论是局部变量还是成员变量,都一样不可修改
2.修饰类,表示此类不能被继承
3.修饰方法,表示此方法不能被重写
继承与组合
继承是is-a的关系,比如狗是动物
组合是has-a的关系,比如汽车有什么
下面是一个学校类,里面有学生类,老师类,员工类