継承: 簡単に言うと、コードの再利用であり、プログラム全体のスケーラビリティが向上します。
動物のクラスには似たような属性や動作がたくさんありますが、それらが特定のクラスに分散していると冗長なコードが多くなり、また新しいクラスを拡張する場合も同様のコードを再度書かなければならず面倒です。
複数のクラスの共通の特徴を抽出し、継承の概念を提案します。継承とは、共通の特徴を抽出し、コードの再利用を実現することです。
継承を使用したい場合、すべてのものが公開目的で継承を使用できるわけではありません。継承を使用したい場合は、is-a 原則を満たす必要があります。
犬も猫も自然に満たされる動物です
したがって、すべての動物クラスに共通のプロパティとメソッドが抽出され、Animal クラスに配置され、特定の Dog クラスと Cat クラスは Animal クラスから継承するだけで済みます。
継承の文法: extendsを使用して親クラスの継承を示します
アクセス修飾子クラスのサブクラス名は親クラスを拡張します {
}
継承が存在するため、共通のプロパティとメソッドはすべて親クラスに配置され、サブクラスは固有のプロパティとメソッドを実装するだけで済みます。
全体的なコード実装がより簡潔になり、拡張が容易になりました。
親クラスと子クラスのメンバーシップ
親クラスとサブクラスに同じ名前のプロパティとメソッドはありません
サブクラスと親クラスのメンバー属性が同じ名前を持つ
アクセスした変数(型を問わず)がサブクラスに存在する場合
ここで a と b はサブクラスに存在し、サブクラスで呼び出される a と b はデフォルトでサブクラスの属性を使用します。
属性がサブクラスに存在しない場合は、親クラスから同じ名前の属性を探します。
同じ名前の属性が親クラスに見つからない場合、コンパイル時にエラーが報告されます。!!
親クラスにプライベートなプライベートフィールドがあり、サブクラスが親クラスを継承する場合、そのプライベートフィールドを直接使用することはできません
この種の継承は暗黙的継承と呼ばれます。
親クラスと子クラス間の呼び出し
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");
}
サブクラスオブジェクトを通じてメソッドにアクセスする場合
メソッドがサブクラスに存在する場合、サブクラスと同じ名前のメソッドが最初にアクセスされます(パラメータに応じて)
例:上記のコードの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不能直接指代父类对象