Java:继承与多态
继承
1.概念: 继承是面向对象三大特征之一。可以使得子类具有父类的属性和方法,还可以在子类中重新定义,追加属性和方法,类继承可以多层继承,最终的子类拥有它所有父类的成员方法和成员变量,成员常量,这个父类可以是直系父类,也可以是父类的父类甚至父类的父类的…父类
2.格式: public class子类名extends父类名{ }
父类,也被称为基类、超类
子类,也被称为派生类
模板样例
package extedns;
public class Father {
public void showf(){
System.out.println("showf方法被调用");
}
}
package extedns;
public class Child extends Father {//extends表示基础,子态继承父态
public void showc(){
System.out.println("showc方法被调用");
}
}
package extedns;
public class Test {
public static void main(String[] args) {
Father f=new Father();
f.showf();
System.out.println();
Child c=new Child();
c.showc();
c.showf();
}
}
输出结果:
showf方法被调用
showc方法被调用
showf方法被调用
好处就是简便代码,同功能可以共用,同功能同修改一次性修改,方便。
坏处就是牵一发动全身。
3.Super(关键字)
注意!对于继承中方法变量重名如何使用/在子类中访问变量,即使用的是this.变量名也是先成员变量再局部变量
public class temp {
private int a=13;
public void show(){
int a=12;
System.out.println(this.a);
}
}
调用show输出的是13
如果成员方法内部本身有变量,优先局部变量,否则选择子类的成员变量,最后才是父类的成员变量, 如果到此都没有,报错结束。 (这块我测试了一下不是很清楚,先放着)
不会考虑父类的父类。
如果需要忽略局部变量,访问本类的成员变量用关键字this,访问父类的成员变量用关键字super。
super访问成员变量
package extedns;
public class Test {
public static void main(String[] args) {
Child c=new Child();
c.show(20);
}
}
package extedns;
public class Child extends Father {
int age=30;
public void show(int age){
System.out.println(age);
System.out.println(this.age);
System.out.println(super.age);
}
}
package extedns;
public class Father {
int age=40;
}
输出结果:
20
30
40
super访问构造方法:
package extedns;
public class Test {
public static void main(String[] args) {
Child c1=new Child();
System.out.println();
Child c2=new Child(20);
}
}
package extedns;
public class Child extends Father {
public Child() {
//super();因为系统自动访问无参构造,所以首先得确保父类中含有无参构造,否则会报错
//子类初始化之前要先对父类初始化,所以调用super访问父类会先访问父类的成员变量int age=0;
//如果不含有无参构造要么自己写一个无参构造,要么就自己写一个super(参数);这样系统就不会自动访问无参构造,而是访问含参构造
System.out.println("调用子类的无参构造");
}
public Child(int age) {
//super();相当于系统自动调用了super(),所以是访问的是父类无参构造
//super(20);这样结果就不会访问父类的无参构造而变成访问父类的含参构造方法。
System.out.println("调用子类的含参构造");
}
}
package extedns;
public class Father {
int age=0;
public Father(){
System.out.println("调用父类的无参构造");
}
public Father(int age) {
System.out.println("调用父类的含参构造");
}
}
输出结果:
调用父类的无参构造
调用子类的无参构造
调用父类的无参构造
调用子类的含参构造
子类中所有的构造方法默认都会访问父类中无参的构造方法为什么呢?
因为子类会继承父类中的数据,可能还会使用父类的数据。所以,子类初始化之前,一定要先完成父类数据的初始化,每一个子类构造方法的第一条语句默认都是: super()(即使你没有写super()系统都会自动调用这一句,访问父类无参构造方法,除非你自己写了一个super(含参)这样就会访问父类含参构造方法)
如果父类中没有无参构造方法,只有带参构造方法,该怎么办呢?
通过使用super关键字去显示的调用父类的带参构造方法 或者 在父类中自己提供一个无参构造方法(一旦类中存在含参构造,系统就不会自动定义无参构造,所以最好自己写一个无参构造)
super访问成员方法:
package extedns;
public class Test {
public static void main(String[] args) {
Child c=new Child();
c.showc();
c.showf();
}
}
package extedns;
public class Father {
public void showf(){
System.out.println("父类的showf被调用");
}
}
package extedns;
public class Child extends Father {
public void showc(){
System.out.println("子类的showc被调用");
}
}
输出结果:
子类的showc被调用
父类的showf被调用
如果子类的成员方法出现和父类的成员方法重名的,优先调用子类的成员方法
子类变成这样:
package extedns;
public class Child extends Father {
public void showc(){
System.out.println("子类的showc被调用");
}
public void showf(){
System.out.println("子类的showf被调用");
}
}
输出结果:
子类的showc被调用
子类的showf被调用
如果子类中出现与父类重名的成员变量但想调用父类的成员变量:
package extedns;
public class Child extends Father {
public void showc(){
System.out.println("子类的showc被调用");
}
public void showf(){
super.showf();//看这!!
System.out.println("子类的showf被调用");
}
}
子类的showc被调用
父类的showf被调用
子类的showf被调用
通过上面三种super的访问我们发现无论是super还是this都只存在于自定义的类中,而不能出现在主函数中。
4.继承中的方法重写
方法重写概述:
子类中出现了和父类中一模一样的方法声明
方法重写的应用:
当子类需要父类的功能,而功能主体子类有自己特有内容时,可以重写父类中的方法,这样,即沿袭了父类的功能,又定义了子类特有的内容
我觉得就是在父类功能基础上扩充了功能,并不会对父类的功能进行修改,不过是父类和子类中有重名方法,先调用子类的方法而已。
package extedns;
public class Test {
public static void main(String[] args) {
Phone p = new Phone();
p.call("林青霞");
NewPhone np = new NewPhone();
np.call("林青霞");
}
}
package extedns;
public class NewPhone extends Phone {
public void call(String name){
System.out.println("正在打开视频功能");
super.call(name);
//==System.out.println("给"+name+"打电话");
}
}
package extedns;
public class Phone {
public void call(String name){
System.out.println("给"+name+"打电话");
}
}
注意!!
如果父类中的public void call(String name)
变成private void call(String name)
,说明call方法是Phone类私有的,只能在Phone类内部进行访问。
public static void main(String[] args) {
Phone p = new Phone();
p.call("林青霞");//报错
}
子类也不能继承父类中被private
修饰的方法。
所以在子类无法对父类修饰符为private的方法进行方法重写。
public void call(String name){
System.out.println("正在打开视频功能");
super.call(name);//报错
}
初次之外,子类对父类进行方法重写要求访问权限不能低于父类的,如果父类是默认修饰符(无public和private)子类要么也是默认修饰符,要么修饰符也是public。
5.继承多类:Java中一个类不能继承多个类,如果要实现多层继承就得在几个类中建立联系,顺序继承。
Java中类只支持单继承,不支持多继承。Java中类支持多层继承。
6.权限修饰符:
public:整个项目都可以使用
protected: 声明为protected的方法和成员变量能被同一个包里的所有类所访问, 能被该类的子类所访问,子类可以和父类不在一个包中(不同包下的子类可以访问父类)。(根据下面的示例,估计是一个不同包的子类继承所需父类,在不同包的主函数想要调用被继承的父类方法,只能通过子类继承父类方法,在不同包的主函数中调用子类方法。)
默认:只能在同一个包使用
private:只能在本类使用