Java基類和派生類


背景:對基類和派生類有更清晰的認識。

從外部看來,派生類是一個與基類具有相同接口的新類,或許還會有一些額外的的方法和域 。但繼承並不僅僅是類的復用。當創建了一個派生類的對象時,該類包含了一個基類的子對象。這個子對象和你用基類直接創建的對象沒有什么兩樣。

二者的區別在於,后者來自於外部,而基類的子對象來自於派生類對象的內部。對基類的子對象初始化時至關重要的,而且也只有一種方法來保證這一點,那就是在派生類的構造器中調用基類的構造器,而基類的構造器具有執行基類初始化所需的所有能力和知識。

     

示例

 

在無參構造器時, java會自動在派生類的構造器中插入對基類的構造器的調用

public class Humans {     
    Humans(){  
        System.out.println("我是人!");  
    }  
      
} 

 

public class Student extends Humans{  
  
    Student(){  
        System.out.println("我是學生!");  
    }  
  
}  
public class test {  
    public static void main(String args[]){  
          new Student();  
    }  
}  

輸出結果為:

      我是人!

     我是學生!

可以發現,總是基類的構造器先被初始化。

示例

但是當構造器有參數時,那就必須使用關鍵字super現實地編寫調用基類構造器的代碼,並且匹配適當的參數列表

public class Humans {  
      
    private String name;  
  
    Humans(String name){  
        System.out.println("我是叫"+name+"的人");  
    }  
  
    public String getName() {  
        return name;  
    }  
  
    public void setName(String name) {  
        this.name = name;  
    }  
  
}  

 

public class Student extends Humans{  
      
    private String name;  
  
    Student(String name){  
        super(name);  
        System.out.println("我是學生!");  
    }  
  
    public String getName() {  
        return name;  
    }  
  
    public void setName(String name) {  
        this.name = name;  
    }  
}  

 

public class test {  
    public static void main(String args[]){  
        new Student("zhangsan");  
    }  
} 

 輸出結果:

我是叫zhangsan的人

我是學生!

如果注釋掉上面的super(name);將會報錯。原因是派生類必須調用基類構造器。因為實例化派生類時,基類也會被實例化,如果不調用基類的構造器,基類將不會被實例化,所以派生類沒有調用基類構造器會報錯。

 

但是如果Humans的代碼變成這樣就不會錯。如下代碼:

public class Humans {  
      
    private String name;  
  
    Humans(){  
        System.out.println("我是人!");  
    }  
    Humans(String name){  
        System.out.println("我是叫"+name+"的人");  
    }  
  
    public String getName() {  
        return name;  
    }  
  
    public void setName(String name) {  
        this.name = name;  
    }  
  
}  
public class Student extends Humans{  
      
    private String name;  
      
    Student(String name){  
        //super(name);  
        System.out.println("我是學生!");  
    }  
  
    public String getName() {  
        return name;  
    }  
  
    public void setName(String name) {  
        this.name = name;  
    }  
}  
public class test {  
    public static void main(String args[]){  
        new Student("zhangsan");  
    }  
}  

輸出結果為:

        我是人!

        我是學生!

 

原因是,如果基類有一個無參的構造器,就算派生類不用super顯示調用基類的構造函數,編譯器也會自動去調用基類的無參構造函數。

所以上面的代碼不會報錯,輸出結果也不是

        我是叫zhangsan的人

        我是學生!

 

而是

        我是人!

        我是學生!

 

示例

派生類繼承了基類的所有public和protected屬性和方法,代碼如下:

public class Humans {  
      
    public String sex;  
      
    protected int age ;  
      
    private String name;  
  
  
    Humans(String sex,String name,int age){  
        this.sex = sex;  
        this.name = name;  
        this.age = age;  
    }  
  
    public String getName() {  
        return name;  
    }  
  
    public void setName(String name) {  
        this.name = name;  
    }  
  
}  
public class Student extends Humans{  
      
    Student(String sex ,String name,int age){  
        super(sex,name,age);  
    }  
}  
public class test {  
    public static void main(String args[]){  
        Student s = new Student("男","zhangsan",10);  
        System.out.println(s.sex);  
        System.out.println(s.name);  
        System.out.println(s.age);  
    }  
}  

 

上面的System.out.println(s.name);會報錯,因為name是private屬性,如需訪問,采用get方法:

System.out.println(s.getName())

輸出結果為:

男

zhangsan

10 

 

示例

如果派生類定義了和基類一樣的屬性或方法,將覆蓋基類的屬性和方法。如將student改為如下代碼:

public class Student extends Humans{  
      
    public String sex;  
      
    protected int age ;  
      
    private String name;  
      
    Student(String sex ,String name,int age){  
        super(sex,name,age);  
    }  
      
    public String getName() {  
        return name;  
    }  
  
    public void setName(String name) {  
        this.name = name;  
    }  
}  

 輸出結果為:

null

null

0

因為只有基類的屬性在構造時賦值了,派生類的沒有,當訪問這些屬性時,訪問的是派生類的屬性,所以全為null或者0。

只有當派生類的屬性也被實例化時,才會得到屬性的值。代碼改為如下:

public class Student extends Humans{  
      
    public String sex;  
      
    protected int age ;  
      
    private String name;  
      
    Student(String sex ,String name,int age){  
        super(sex,name,age);  
        this.sex = sex;  
        this.name = name;  
        this.age = age;  
    }  
      
    public String getName() {  
        return name;  
    }  
  
    public void setName(String name) {  
        this.name = name;  
    }  
}  

輸出結果為:

男
zhangsan
10  

要注意的是,super必須在構造器的最前面,不然會報錯

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM