寫在前面:這幾天仍然課程很多,正在積極學習恢復更新,這裏的類與對象會多分享幾個小節
學習內容安排
JAVA基礎課程學習:數據類型(一)、運算符表達式和程序結構控制(二)、面向對象基礎:類與對象和接口(三)、面向對象基礎:繼承抽象多態封裝(四)、異常類和常用實用類(五)、組件和事件處理(六)、IO和JDBC(七)、泛型和集合函數(八)。
四、面向對象基礎:繼承抽象多態封裝
前面我們分享瞭如何來定義類,以及類和變量的相關概念,今天主要來分享一下繼承、子類與對象、方法重寫、super、final、對象的上轉型對象、abstract、接口。首先我們來講一下繼承。
繼承
所謂繼承就是子輩繼承父輩的一些東西,也就是子類繼承父類的一些屬性或者方法,然後子類還可以增加自己的一些屬性或者方法,我們使用extend來進行子類與父類的繼承,
//這裏定義了一個F1父類,有height、weight、money,然後父親可以掙錢和唱歌
package tt;
class F2 {
public int height;
float weight; //友好的不再同一個包就不行了
private float money = 100;
void sing(){
System.out.println("song");
}
}
//下面來定義一個子類
//子類有全新的書信id,還可以學習
class SS extends F2 {
String id;
SS(){
}
void study(){
}
public static void main(String[] args) {
SS ss = new SS();
ss.height = 180;
//先調用父類的構造函數在調用自己的構造函數
ss.sing();//自動調用不帶參數的父類的構造方法方法
ss.study();
}
}
對於子類可以對父類的變量進行賦值更改,還可以調用父類的方法,比如這裏調用了父類的sing和自己類的study函數,於是輸出的是,
song
子類與對象
子類創建對象時,子類的構造方法總是先調用父類的某個構造方法,完成父類部分的創建,然後再調用子類自己的構造方法,完成子類部分的創建。如果子類的構造方法沒有明確的指向父類的哪個構造方法,那麼就調用父類的不帶參數的構造方法。如果父類的構造方法都帶參數那麼就必須輸入參數,可以利用super進行調用,但在子類的構造函數中第一句就必須是super。
對於子類只能操作被繼承的成員變量,而沒有去權限繼承的變量,則可以使用調用父類方法,來進行使用。
package tt;
class F2 {
public int height;
float weight; //友好的不再同一個包就不行了
private float money = 100;
F2(int x){
System.out.println(x);
}
void getMoney(){
System.out.println(money);
}
void sing(){
System.out.println("song");
}
}
//下面來定義一個子類
//子類有全新的書信id,還可以學習
class SS extends F2 {
String id;
SS(int y){
super(y); //super調用父輩構造方法
}
void study(){
}
public static void main(String[] args) {
SS ss = new SS(5); // 調用帶參數的構造函數
ss.height = 180;
ss.sing();
ss.study();
ss.getMoney(); //調用含不可使用的變量的方法
}
}
於是可以得到輸出結果應該是返回了5的父輩構造函數,sing方法裏的song已經getMoney裏的money值。
5
song
100.0
這裏值得注意的是子類不能繼承父類的構造方法,但是可以使用super進行調用。
方法重寫
所謂方法重寫就是,原本在父類裏存在的方法,可以在子類裏進行重新設置,然後輸出。如果子類重寫了父類的方法,那麼在子類中調用該方法時默認使用重寫後的方法。重寫的時候需要注意的是,不能降低方法的訪問權限,但是可以提高,
package tt;
//定義父類
class driveC1 {
private void passRule(int A, int B, int C){
int total = A + B + C;
if(total >= 60){
System.out.println("通過了C1駕駛考試");
}else{
System.out.println("沒有通過C1哦");
}
}
}
//定義子類
class driveA1 extends driveC1{
public void passRule(int A, int B, int C){//加大了子類的權限
int total = A + B + C;
if(total >= 90){
System.out.println("通過了A1駕駛考試");
}else{
System.out.println("沒有通過A1哦");
}
}
}
public class Csdn3_2_2{
public static void main(String[] args) {
int A = 50, B = 20, C = 10;
driveA1 driver = new driveA1();//調用子類
driver.passRule(A, B, C);//調用重寫方法
}
}
根據上面說的,調用重寫的反覆默認爲子類重寫後的方法,所以輸出結果應該是沒有通過A1哦,
沒有通過A1哦
super、final關鍵字
下面來講一下super和final關鍵字,suoer關鍵字是用來操作被隱藏的成員變量和方法的,如果子類想調用父類中隱藏的成員變量與方法的話就可以使用super.x、super.play(),進行調用。還有super可以來調用構造函數,在前面已經涉及。
對於final關鍵字其實就是用來終止繼承的延續性,也就是該類不能再有子類的生成,final可以對於類別也可以對於方法和變量,
package tt;
//生成父類
class Sum {
int n;
float f(){
float sum = 0;
for(int i = 1; i < n; i++){
sum += i;
}
return sum;// 定義一個求和的函數
}
}
//生成子類
final class Ave extends Sum{
int n = 6;
Ave(){
double x = f();
System.out.println(x); //子類的構造函數
}
float f(){
float c;
super.n = 5; //調用父類的n
c = super.f();//調用父類的f,類似於this
return c/n;
}//重寫f函數
public static void main(String[] args) {
Ave ave =new Ave();
}
}
從上面的程序我們可以看到,我們首先使用了子類的n=6與父類的n=5,也使用了子類的f()求平均方法,也調用了父類的f()求和方法,於是我們得到輸出值爲,
1.6666666269302368
對象的上轉型對象
這個名字看上去比較複雜,當然讀上去也比較複雜,其實理解起來還是不那麼複雜的,我們舉個例子,我們有父類並且聲明瞭a,還有子類聲明瞭b,當我們令a = b時,相當於就是將b從子類升級成爲了父類中的變量,會獲得父類中的隱藏變量,但同時會失去一些能力,此時就稱a爲對象的上轉型對象,
具體的能力如下,
能力名稱 | 對象類型 |
---|---|
隱藏的變量 | 對象的上轉型對象 |
繼承的變量 | 對象的上轉型對象、普通對象 |
新增的變量 | 普通對象 |
繼承或重寫的方法 | 對象的上轉型對象、普通對象 |
新增的方法 | 普通對象 |
從這張表可以看出,對象的上轉型對象不能夠使用新增變量以及新增方法,
package tt;
public class Csdn3_2_4 {
public static void main(String[] args) {
Father man;
Child child = new Child();
man = child;//設置上轉型變量
man.speak("Yes, I am a man"); //繼承的方法
Child son = (Child) man;//將滿轉化爲Child類
son.learn(10);//新方法
}
}
//設置父類
class Father{
void speak(String s){
System.out.println(s);
}
}
//設置子類
class Child extends Father{
void learn(int a){
int c = 2 * a;
System.out.println(c);
}//新方法
void speak(String s){
System.out.println("******"+s);
}//重寫的方法
}
我們可以通過上述程序看到,我們的父親有說話的能力,但孩子只能呀呀呀的說話,但孩子有新的學習的能力,如果我們將孩子中的一個變量賦值給父類中的變量,那麼以爲着上轉型變量將無法學習,但能夠說話,因爲這裏存在重寫,所以還是孩子一樣的說話。然後可以通過將上轉型變量強制變爲孩子一類,才能夠使用learn()方法,
******Yes, I am a man
20
abstract
下面我們來講一下abstract類和abstract方法,所謂abstract其實就是創建抽象類與抽象方法,其作用就是暫時只是聲明有這麼個類或者方法存在,但不去實現它,一般就作爲架構師的角度,將各種功能先進行佈局,然後讓下面的人進行完成,
package tt;
//設置父類抽象類,意味着類中包含抽象方法
abstract class Test {
void read(){
}//已有的read方法
abstract void add();//抽象的求和add方法
abstract void sum(int x); //抽象的求和方法,這些都需要下面的人來完成
}
//設置子類1,這個子類就必須完成父類的抽象方法工作,或者繼續繼承給下一個人完成
abstract class Test2 extends Test{
void sum(int x){//完成sum()方法
}//必須要來實現,部分完成,讓下面的在來完成add()
}
//最後設置子類來完成最後的add方法
class Test3 extends Test2{
void add(){
}
}
接口
在接口之前我們提一個開閉原則,這是一種程序設計的思想,開也就是系統對擴展開放,閉也就是對修改關閉。這樣的做法就能夠保證再設計後產生許多不必要的修改。
好了,我們來簡單的說一下接口。爲了克服JAVA單繼承的缺點,JAVA使用了接口,也就是一個類可以實現多個接口,接口的特點,
1.由interface關鍵詞修飾的稱之爲接口;
2.接口中可以定義成員變量,但是這些成員變量默認都是public static final的常量。
3.接口中沒有已經實現的方法,全部是抽象方法。
4.一個類實現某一接口,必須實現接口中定義的所有方法。
5.一個類可以實現多個接口。繼承與接口的區別
總之接口就是一個更加抽象的概念,下面我們來說明一下接口在日常生活中的使用示意圖,一個項目有三級,負責人、小組長和員工,一般負責人利用interface寫好接口,也就是構造好需要的內容框架,然後分發給下面的小組長完成,小組長則針對接口構造抽象類,或者完成方法,然後再給員工完成具體實現。
我們用一個小的實例來展示一下接口,interface聲明接口,implement鏈接接口
package tt;
public interface Csdn3_2_6 { //創建接口
void sum();
int add(int x, int y);
}
abstract class NewClass implements Csdn3_2_6{
public void sum(){//因爲接口的時候是public所以需要在前面加上public
}//將剩下的add交給下面的完成
}
class NewClass1 extends NewClass{//完成add類
public int add(int x, int y){
return x + y;
}
}
結語
以上就是本節的全部內容,主要涉及的就是繼承方面的相關東西。
今天的更新,將接口的簡單內容加在了最後。
謝謝閱讀。