继承:简单来说就是代码复用,增加整个程序的扩展性。
不同的动物类,具有很多相似的属性和行为,这些属性和方法要是分散在具体的类中,就会有很多的冗余代码,新扩展一个类也比较麻烦,因为相似的代码都得再写一遍。
将多个类的一些共性抽取出来,提出了继承的概念--继承就是再进行共性提取,实现代码复用!
要想使用继承,不是所有东西为了公用都能使用继承,要想使用继承,必须满足is - a原则
Dog和Cat都是天然满足 is an Animal
因此将所有动物类的共同的属性和方法提取出来放在Animal类中,具体的Dog,Cat类也罢只需要继承自Animal类即可!
继承的语法:使用extends表示继承父类
访问修饰符 class 子类名称 extends 父类{
}
有了继承的存在,将所有共性属性与方法放在父类中,子类只需要实现独有的属性和方法即可
整体代码实现更加简洁,方便进行扩展
父类和子类的成员关系
父类和子类不存在同名的属性和方法
子类和父类成员属性同名
当访问的变量(不管类型)子类中存在
此处的a和b子类中存在,则在子类中调用的a和b默认就会使用子类中的属性
若子类中不存在该属性,才会从父类中寻找同名属性
若父类中也没有找到同名属性,编译报错!!!
当父类中存在private私有域,子类在继承父类时,私有域无法直接使用
这种继承称为隐式继承。
父类和子类之间的调用
public void methodA(){
System.out.println("Base中的methodA");
}
public void methodB(){
System.out.println("Base中的methodB");
}
public static void main(String[] args){
Derived d = new Derived();
d.methodA(10);
d.methodA();
d.methodB();
d.methodC();
}
}
//子类
class Derived extends Base{
public void methodA(int a) {
System.out.println("Derived中的methodA");
}
public void methodB() {
System.out.println("Derived中的methodB");
}
public void methodC() {
System.out.println("Derived中的methodC");
}
当通过子类对象访问方法时
若子类中存在该方法,则优先访问子类的同名方法(要看参数)
eg:上面代码的methodB(),子类和父类完全相同,方法名称,参数类型完全相同,则优先访问子类的methodB
若子类不存在该方法,则会从父类中寻找是否存在该方法,存在则调用,不存在则编译出错。一定要注意隐式继承问题
eg:上面代码的methodA(),子类和父类都有名称位methodA(),但是参数不同,根据名称 + 参数来决定到底调用的是哪个方法
当产生子类对象时,默认先调用父类的构造方法产生父类对象而后调用子类构造方法产生对象
先产生父类对象然后产生子类对象(先有爹才有儿)
产生N个对象,要调用N次构造方法,只要调用子类的构造方法,就会先调用父类的!
只要产生子类对象,一定是先调用父类构造方法产生父类对象之后再调用子类构造方法产生子类对象
super:表示直接从父类中寻找成员变量或成员方法
super修饰属性,表示直接寻找的父类的同名属性 private属性无法调用
super修饰方法
2.1 super修饰普通成员方法,表示直接在父类中寻找同名方法
public void methodB() {
//明确表示调用父类的methodB方法
super.methodB();
System.out.println("Derived中的methodB");
}
注意: this.方法名称 从当前类中寻找同名方法
super.方法名称 从父类中寻找同名方法
2.2super修饰构造方法,表示显示在子类构造方法中调用父类的构造方法
public class NewBase{
int a;
public NewBase(int a){
this.a = a;
System.out.println("父类的无参构造");
}
public static void main(String[] args){
//产生子类对象
Child child = new Child();
//只要产生子类对象,要调用子类构造方法,就会先调用父类构造
Child child1 = new Child();
}
}
//子类
class Child extends NewBase{
public Child(){
//如果是无参构造,可以省略该语句
//如果父类中没有无参构造,则在子类的构造方法首行必须显示的使用super(参数)来调用父类的有参构造
super(10);
System.out.println("子类的无参构造");
}
}
注意:
当父类存在无参构造,则子类构造方法首行可以不写super( );
如果父类中没有无参构造,则在子类的构造方法首行必须显示的使用super(参数)来调用父类的有参构造
当存在父类继承时,一般在子类中不出现this的构造方法调用
子类的构造方法首行必须使用super,this的构造方法调用也要放首行时会如下所示!
最后简要总结
继承 :提高代码的复用性,方便进行子类、子功能的扩展,将所有共性的内容放在父类(基类),子类只需要关注子类独有的属性和功能
要使用继承必须满足 is a 原则
Dog is an Animal
Cat is an Animal
Flower is not an Animal
使用关键字 extends表示继承父类
继承分为隐式继承和显示继承
父类中的private域,子类实际上也是继承下来了,但是无法直接使用
父类中的public,protected等域,属于显示继承,子类之中可以直接使用
super :
super修饰属性表示直接寻找父类的同名属性
super修饰方法表示寻找父类的同名方法
super调用父类的构造方法 :
在实例化子类对象时首先调用父类的构造方法先产生父类对象后使用子类构造产生子类对象
当调用的父类的无参构造 super(); //可以省略
但是若父类中只有有参构造,则必须在子类的构造方法首行显示调用super(参数)。表示调用父类的构造方法,有继承的子类中,保留super的首行调用
super调用父类的普通方法 :super.方法名称(参数);
this可以表示当前对象的引用,但是super不能直接指代父类对象