日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > java >内容正文

java

java 重写方法 访问权限_为何Java中子类重写方法的访问权限不能低于父类中权限(内含里氏替换原则)...

發布時間:2025/3/20 java 29 豆豆
生活随笔 收集整理的這篇文章主要介紹了 java 重写方法 访问权限_为何Java中子类重写方法的访问权限不能低于父类中权限(内含里氏替换原则)... 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

為何Java中子類重寫方法的訪問權限不能低于父類中權限

因為 向上轉型及Java程序設計維護的原因

例:

假設一個父類A 擁有的方法public void setXXX(){}可以被其他任意對象調用這個方法被子類B 覆寫后 為void setXXX(){}即默認的訪問權限只能被本包極其子類 所訪問假設其他包中的對象 C調用 方法為:

get( A? a){

a.setXXX();}

而此時傳入的對象為B類對象,假設為b此時b將轉型為a但是b中的setXXX() 調用權限

已經被縮小了這將造成錯誤。所以子類對象不能比父類對象訪問權限大

以上只是一個例子還有其他出于易維護、易代碼結構設計的設計思想原因

其他:子類中重寫的方法拋出的異常應該為父類中方法的子異?;蛳嗤惓?#xff0c;并且拋出的異常種類不能多于父類中的方法。

實際上是遵循里氏替換原則。

一、里氏替換原則的定義

1、里氏替換原則通俗的來講就是:子類可以擴展父類的功能,但不能改變父類原有的功能。

2、里氏代換原則告訴我們,在軟件中將一個基類對象替換成它的子類對象,程序將不會產生任何錯誤和異常,反過來則不成立,如果一個軟件實體使用的是一個子類對象的話,那么它不一定能夠使用基類對象。

3、里氏代換原則是實現開閉原則的重要方式之一,由于使用基類對象的地方都可以使用子類對象,因此在程序中盡量使用基類類型來對對象進行定義,而在運行時再確定其子類類型,用子類對象來替換父類對象。

二、里氏替換原則包含的含義

1、子類可以實現父類的抽象方法,但是不能覆蓋父類的非抽象方法

在我們做系統設計時,經常會設計接口或抽象類,然后由子類來實現抽象方法,這里使用的其實就是里氏替換原則。子類可以實現父類的抽象方法很好理解,事實上,子類也必須完全實現父類的抽象方法,哪怕寫一個空方法,否則會編譯報錯。

里氏替換原則的關鍵點在于不能覆蓋父類的非抽象方法。(盡量不要重寫)父類中凡是已經實現好的方法,實際上是在設定一系列的規范和契約,雖然它不強制要求所有的子類必須遵從這些規范,但是如果子類對這些非抽象方法任意修改,就會對整個繼承體系造成破壞。而里氏替換原則就是表達了這一層含義。

2、子類中可以增加自己特有的方法

在繼承父類屬性和方法的同時,每個子類也都可以有自己的個性,在父類的基礎上擴展自己的功能。前面其實已經提到,當功能擴展時,子類盡量不要重寫父類的方法,而是另寫一個方法。

3、當子類覆蓋或實現父類的方法時,方法的前置條件(即方法的形參)要比父類方法的輸入參數更寬松。

4、當子類覆蓋或實現父類的方法時,方法的后置條件(即方法的返回值)要比父類方法的返回值更嚴格。

現在我們可以對以上四層含義逐個講解。

子類可以實現父類的抽象方法,但是不能覆蓋父類的非抽象方法

在我們做系統設計時,經常會設計接口或抽象類,然后由子類來實現抽象方法,這里使用的其實就是里氏替換原則。子類可以實現父類的抽象方法很好理解,事實上,子類也必須完全實現父類的抽象方法,哪怕寫一個空方法,否則會編譯報錯。

里氏替換原則的關鍵點在于不能覆蓋父類的非抽象方法。父類中凡是已經實現好的方法,實際上是在設定一系列的規范和契約,雖然它不強制要求所有的子類必須遵從這些規范,但是如果子類對這些非抽象方法任意修改,就會對整個繼承體系造成破壞。而里氏替換原則就是表達了這一層含義。

在面向對象的設計思想中,繼承這一特性為系統的設計帶來了極大的便利性,但是由之而來的也潛在著一些風險。就像開篇所提到的那一場景一樣,對于那種情況最好遵循里氏替換原則,類C1繼承類C時,可以添加新方法完成新增功能,盡量不要重寫父類C的方法。否則可能帶來難以預料的風險,比如下面一個簡單的例子:

public?class?C {

public?int?func(int?a, int?b){

return?a+b;

}

}

public?class?C1 extends?C{

@Override

public?int?func(int?a, int?b) {

return?a-b;

}

}

public?class?Client{

public?static?void?main(String[] args) {

C c = new?C1();

System.out.println("2+1="?+ c.func(2, 1));

}

}

運行結果:2+1=1

上面的運行結果明顯是錯誤的。類C1繼承C,后來需要增加新功能,類C1并沒有新寫一個方法,而是直接重寫了父類C的func方法,違背里氏替換原則,引用父類的地方并不能透明的使用子類的對象,導致運行結果出錯。

子類中可以增加自己特有的方法

在繼承父類屬性和方法的同時,每個子類也都可以有自己的個性,在父類的基礎上擴展自己的功能。前面其實已經提到,當功能擴展時,子類盡量不要重寫父類的方法,而是另寫一個方法,所以對上面的代碼加以更改,使其符合里氏替換原則,代碼如下:

public?class?C {

public?int?func(int?a, int?b){

return?a+b;

}

}

public?class?C1 extends?C{

public?int?func2(int?a, int?b) {

return?a-b;

}

}

public?class?Client{

public?static?void?main(String[] args) {

C1 c = new?C1();

System.out.println("2-1="?+ c.func2(2, 1));

}

}

運行結果:2-1=1

當子類覆蓋或實現父類的方法時,方法的前置條件(即方法的形參)要比父類方法的輸入參數更寬松

import?java.util.HashMap;

public?class?Father {

public?void?func(HashMap m){

System.out.println("執行父類...");

}

}

import?java.util.Map;

public?class?Son extends?Father{

public?void?func(Map m){//方法的形參比父類的更寬松

System.out.println("執行子類...");

}

}

import?java.util.HashMap;

public?class?Client{

public?static?void?main(String[] args) {

Father f = new?Son();//引用基類的地方能透明地使用其子類的對象。

HashMap h = new?HashMap();

f.func(h);

}

}

運行結果:執行父類...

注意Son類的func方法前面是不能加@Override注解的,因為否則會編譯提示報錯,因為這并不是重寫(Override)。

當子類的方法實現父類的抽象方法時,方法的后置條件(即方法的返回值)要比父類更嚴格

import?java.util.Map;

public?abstract?class?Father {

public?abstract?Map func();

}

import?java.util.HashMap;

public?class?Son extends?Father{

@Override

public?HashMap func(){//方法的返回值比父類的更嚴格

HashMap h = new?HashMap();

h.put("h", "執行子類...");

return?h;

}

}

public?class?Client{

public?static?void?main(String[] args) {

Father f = new?Son();//引用基類的地方能透明地使用其子類的對象。

System.out.println(f.func());

}

}

執行結果:{h=執行子類...}

總結

繼承作為面向對象三大特性之一,在給程序設計帶來巨大便利的同時,也帶來了一些弊端,它增加了對象之間的耦合性。因此在系統設計時,遵循里氏替換原則,盡量避免子類重寫父類的方法,可以有效降低代碼出錯的可能性。

我們都知道面向對象有三大特性:封裝、繼承、多態。所以我們在實際開發過程中,子類在繼承父類后,根據多態的特性,可能是圖一時方便,經常任意重寫父類的方法,那么這種方式會大大增加代碼出問題的幾率。比如下面場景:類C實現了某項功能F1。現在需要對功能F1作修改擴展,將功能F1擴展為F,其中F由原有的功能F1和新功能F2組成。新功能F由類C的子類C1來完成,則子類C1在完成功能F的同時,有可能會導致類C的原功能F1發生故障。這時候里氏替換原則就閃亮登場了。

總結

以上是生活随笔為你收集整理的java 重写方法 访问权限_为何Java中子类重写方法的访问权限不能低于父类中权限(内含里氏替换原则)...的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。