子類重寫父類成員方法

最近在學習到Java的繼承和多態時遇到了這樣的一個問題:關於繼承鏈中子類對父類的私有方法是否能夠覆蓋的問題,在此記錄一下本身對這個問題解決之後的一些心得。html

 

首先要明確:子類是不可以覆蓋(重寫)父類的私有方法的。比較直觀的理由是,子類要可以重寫父類的方法的前提條件是繼承,子類對父類的私有方法並不繼承,也沒有訪問權限,天然也是不能重寫的。接下來看一個例子:java

 

 

[java] view plaincopy函數

<span style="font-size:14px;">public class Test {  學習

    public static void main(String[] args) {  測試

        new A().printPerson();  this

        new B().printPerson();  spa

    }  htm

}  對象

  

class A {  blog

    public void printPerson() {  

        System.out.println(getInfo());  

    }  

    private String getInfo() {  

        return "A";  

    }  

}  

  

class B extends A{  

    public String getInfo() {  

        return "B";  

    }  

}</span>  

運行結果是 A A。若是將private修飾詞去掉,換成protected和public修飾,運行結果是A B這是毫無疑問的,由於那正是B重寫了父類A的getInfo方法;而加上了private修飾詞之後,父類A的getInfo和子類B的getInfo實際上就是兩個無關的方法,由於私有方法是不能被子類重寫的,私有方法並非父類接口的一部分,只是隱藏在父類中的一段程序代碼。

但是爲何使用子類B的實例調用printPerson,結果是打印A呢?要注意到printPerson方法是在父類A中定義的,所以剛執行new B().printPerson()這行代碼時,編譯器在子類B中沒法找到匹配的printPerson方法,因而到父類A中去尋找;此時在父類A中找到了匹配的printPerson方法,並調用該方法。

 

此處須要說起一會兒類在繼承父類時對父類的成員變量及方法繼承的問題。對於使用protected或者public修飾的成員變量及方法,會被子類繼承,且可經過子類直接調用,那麼,對於子類不可見的private成員,以及沒有修飾詞修飾的成員(若子類與父類在不一樣的包中,這一類成員也是對子類不可見的),他們不被子類繼承,那麼在子類的實例所表明的內存空間中,這些成員是否存在呢?答案是確定的,父類的私有變量及方法雖然不會被子類繼承,對於子類來講不可見,但當建立了子類的實例的時候,這些成員同樣會被加載入內存,並「隱藏」在內存當中。

 

所以,經過子類B的實例調用printPerson方法,會在父類的成員中尋找匹配的printPerson方法,找到之後,進入printPerson的方法體,調用getInfo方法,程序回到上層去尋找getInfo方法的匹配,並在內存空間中尋找到了A中的getInfo方法,同時因爲該getInfo方法是私有的,沒法被重寫,所以不會觸發java的動態綁定機制,因而直接調用該方法。所以,經過B的實例調用printPerson,打印的結果也是A了。

============================================

 

最近學習繼承,從書中看到子類繼承父類,子類擁有父類全部的屬性和方法,因而使用程序去驗證,發現父類的私有屬性和私有方法,子類是不能訪問的,固然一些父類的私有屬性可能能夠經過相應的方法訪問到,可是私有的方法彷佛不能簡單的訪問,這裏暫不考慮Java反射機制,因而我分析,子類不能繼承父類私有的屬性及方法,可是分析了內存後,我發現我是錯的,在一個子類被建立的時候,首先會在內存中建立一個父類對象,而後在父類對象外部放上子類獨有的屬性,二者合起來造成一個子類的對象。因此所謂的繼承使子類擁有父類全部的屬性和方法其實能夠這樣理解,子類對象確實擁有父類對象中全部的屬性和方法,可是父類對象中的私有屬性和方法,子類是沒法訪問到的,只是擁有,但不能使用。就像有些東西你可能擁有,可是你並不能使用。因此子類對象是絕對大於父類對象的,所謂的子類對象只能繼承父類非私有的屬性及方法的說法是錯誤的。能夠繼承,只是沒法訪問到而已。

 

當子類覆蓋父類的成員變量時,父類方法使用的是父類的成員變量,子類方法使用的是子類的成員變量

 

(1)子類覆蓋父類的方法,必須有一樣的參數返回類型,不然編譯不能經過

          (2)子類覆蓋父類的方法,在jdk1.5後,參數返回類能夠是父類方法返回類的子類

         (3)子類覆蓋父類方法,能夠修改方法做用域修飾符,但只能把方法的做用域放大,而不能把public修改成private

          (4)子類方法可以訪問父類的protected做用域成員,不可以訪問默認的做用域成員

         (5)子類的靜態方法不能隱藏同名的父類實例方法

 

 

 

 不能繼承,子類只能在父類中寫一個public的getXXX的方法來獲取父類中的private屬性,子類就調用父類的getXXX來獲取private屬性

 

 父類中的公有方法和域(屬性),在類繼承中將會被子類繼承,可是私有的將不能被繼承。

 

那麼在繼承中子類如何才能繼承到父類的私有域呢?

 

答案是:在子類的構造方法中經過super()方法調用父類的構造方法。

 

也就是,在構造子類的同時,爲子類構造出跟父類相同的域。如此就在子類的對象中,也擁有了父類聲明的域了。

 

而且咱們也應該這樣作。

 

[html] view plaincopy

public class Person{  

    private String name;  

      

    public Person(String name){  

        this.name = name;  

    }  

      

    public void setName(String name){  

        this.name = name;  

    }  

      

    public String getName(){  

        return name;  

    }  

}  

[html] view plaincopy

public class Student extends Person{  

      

    public Student(String name){  

        super(name);  

    }  

}  

 

 

 

[html] view plaincopy

public class TestStudent{  

    public static void main(String[] args){  

      

        Student mStudent = new Student("abc");  

        String mName = mStudent.getName();  

        System.out.println("Name is : " + mName);  

          

        mStudent.setName("efg");  

        mName = mStudent.getName();  

        System.out.println("Name is : " + mName);  

          

    }  

}  

打印結果爲:

 

Name is : abc

 

Name is efg

 ============================================

 

Java-子類沒有繼承父類的私有變量和私有方法

 

  在Java子類有沒有繼承父類的私有變量?關於這個問題在網上找了好久,也沒有一個明確的答案。因而綜合你們的觀點,本身總結了一下。 

   

  官方文檔的解釋:「A subclass does not inherit the private members of its parent class. However, if the superclass has public or protected methods for accessing its private fields, these can also be used by the subclass.」。原文地址:Inheritance 

  那麼問題來了。以前在作Java實驗時,爲何Manger類能使用Employee的私有屬性呢? 

  我找了一下答案: 

  觀點一: 

  「父類中的公有方法和域(屬性),在類繼承中將會被子類繼承,可是私有的將不能被繼承。那麼在繼承中子類如何才能繼承到父類的私有域呢?答案是:在子類的構造方法中經過super()方法調用父類的構造方法。」參考:Java中子類繼承了父類的私有屬性及方法嗎?、 

  寫了測試代碼體會了一下:

 

public class Father 

{

    private int a;

    public Father()

    {

 

    }

    public Father(int a)

    {

        this.a = a;

    }

    public int getA()

    {

        return this.a;

    }

}

 

public class Children extends Father

{

    int b;

    public Children()

    {

 

    }

    public Children(int a,int b)

    {

        //this.a = a;

        super(a);

        this.b = b;

    }

}

 

public class Main 

{

    public static void main(String[] args) 

    {

        Children child1 = new Children(13,35);

        System.out.println(child1.b+"  "+child1.getA());

 

    }

 

}

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

  觀點二: 

  「父類的任何成員變量都是會被子類繼承下去的。實際上,private,public,protected和繼承沒有關係,他們對成員函數和變量的限制只是在成員的可見性上。」參考:私有的成員能被子類繼承嗎? 

   

  觀點三: 

  「父類的private變量,也會被繼承而且初始化在子類父對象中,只不過對外不可見。」。他這個觀點的提出是從內存上分析的,值得借鑑。參考:JAVA 繼承 父類子類 內存分配 

   

  個人總結: 

  從繼承的概念來講,private和final不被繼承。Java官方文檔上是這麼說的。 

  從內存的角度來講,父類的一切都被繼承(從父類構造方法被調用就知道了,由於new一個對象,就會調用構造方法,子類被new的時候就會調用父類的構造方法,因此從內存的角度來講,子類擁有一個完整的父類)。子類對象所引用的內存有父類變量的一份拷貝。 

  如圖所示,父類爲Person類,子類爲Student類。首先明確子類不能繼承父類的構造方法。這就是爲何子類的默認的構造方法會自動調用父類的默認的構造方法。 

  在子類的構造方法中經過super()方法調用父類的構造方法。也就是,在構造子類的同時,爲子類構造出跟父類相同的域。如此就在子類的對象中,也擁有了父類聲明的域了。

相關文章
相關標籤/搜索