21   繼承及相關之修飾子、關鍵字

依據民法的親屬˙繼承篇,繼承者頂多只能獨得或均分被繼承者的所有財產,甚至還會被課一大筆遺產稅,繼承之後,被繼承者的財產就轉移了,換了個所有者。但Java的類別就不同了,除了得到被繼承類別的所有功能之外,還可自行修改及增添功能,當然也有一些不能達到所有原功能的一些限制,且原類別還存在,還可很博愛的被繼承。這大概也是Java的繼承關鍵字不使用inherits,而使用extends的關係吧!

 

[21-1父類別與子類別]

繼承是將類別的成員傳承給其他類別,可以多層的一直繼承下去,對被繼承(傳承)的類別稱為父類別(有時也稱為super類別、base類別),繼承(被傳承)的類別稱為子類別。所有類別的根源類別,也就是最頂端的類別為Object,任何沒有extends關鍵字指名繼承的類別,都是繼承自Object類別。

繼承使用extends關鍵字。

 

<格式>

class 子類別名稱  extends  父類別名稱 {   子類別變更敘述    }

 圖21-1繼承圖示

 

 

[21-2單純繼承]

子類別繼承時,對父類別成員不作任何變更,是為單純繼承,當然類別名稱也不同,單純繼承比較像人類的繼承。此時「子類別變更敘述」之部分為空白。

<範例>

class Inhfat1 {                                              

  int x = 7 ;

  char y = 'a' ;

  void inhmd( ) {

    System.out.println(y + "=" + x) ; }  }

 

class Inhson1 extends Inhfat1{ }   // {   }內為空白

 

class Inhmain1 {

  public static void main(String[ ] args) {

Inhson1 aaa = new Inhson1( ) ;

Inhson1 bbb = new Inhson1( ) ;

aaa.inhmd ( ) ;   //a=7

bbb.x = 10 ;

bbb.inhmd ( ) ;   // a=10

aaa.x = 11 ;

aaa.y = 'k' ;

aaa.inhmd ( ) ;  }  }

執行結果:C:\js>java Inhmain1

a=7

a=10

k=11

 圖21-2

 

 

[21-3增加父類別成員以外成員之繼承]

除了繼承父類別所有成員之外,子類別並新增欄位、方法等成員。

<範例>

classInhfat2 {

  int x = 7 ;

  char y = 'a' ;

  void inhmd1( ) {

    System.out.println(y + "= " + x) ;

  }

}

 

class Inhson2 extends Inhfat2{

int z = 9 ; //新增欄位

void inhmd2( ) { //新增方法

System.out.println("x+z= " +( x+z)) ;

  }

}

 

class Inhmain2 {

  public static void main(String[ ] args) {

Inhson2 ccc = new Inhson2( ) ; //建立物件

ccc.x = 11 ;

ccc.y = 'm' ;

ccc.z =18 ;

ccc.inhmd1( ) ;

ccc.inhmd2( ) ;

  }

}

執行結果:C:\js>java Inhmain2

m= 11

x+z= 29

 

 

[21-4覆寫(override)]

在子類別裡定義一個方法,其名稱、參數、傳回值(同回傳值)型別與父類別完全相同,但是其內容不同,藉以取代父類別之方法。5.0版本另增加傳回值型別不同之覆寫。

<範例>

class Inhfat3 {

  int x = 7 ;

  char y = 'a' ;

  void inhmd( ) {

    System.out.println(y + "=" + x) ;

  }                                                              

}

 

class Inhson3 extends Inhfat3{          

int z = 9 ;

void inhmd( ) {

System.out.println("x+z=" + (x+z)) ;

  }

}

 

class Inhmain3 {

  public static void main(String[ ] args) {

inhson3 ddd = new inhson3( ) ;

ddd.z = 11 ;

ddd.x = 14 ;

ddd.y = 'm' ;

ddd. inhmd( ) ;

  }

}

執行結果:C:\js>java Inhmain3

x+z=25

 

 

[21-5 private修飾子與繼承]

[21-5-1 private成員繼承後無法使用]

父類別private成員,子類別繼承後無法使用,也無法將父類別建立物件使用。

[範例]

class Inhfat4 {

private int x = 7 ;

  char y = 'a' ;

  void inhmd1( ) {

    System.out.println(y + "=" + x) ;  }  }

 

class Inhson4 extends Inhfat4{ //繼承

  int z = 9 ;

  void inhmd2( ) {

    System.out.println("x+z=" + (x+z)) ;  }  }

 

class inhmain4 {

  public static void main(String[ ] args) {

    Inhfat4 eee = new Inhfat4( ) ;  //父類別建立物件

    eee.x = 10 ; 

    eee.inhmd1( ) ;  

    Inhson4 fff = new Inhson4( ) ;  //子類別建立物件

    fff.x = 15 ; 

    fff.inhmd1( ) ;  

    fff.inhmd2( ) ;  }  }

 

編譯結果:C:\js>javac inhmain4.java

inhmain4.java:10: error: x has private access in Inhfat4

    System.out.println("x+z=" + (x+z)) ;  }  }

                                 ^

inhmain4.java:15: error: x has private access in Inhfat4

    eee.x = 10 ;

       ^

inhmain4.java:18: error: x has private access in Inhfat4

    fff.x = 15 ;

       ^

3 errors

 

[21-5-2透過非private的方法可存取private欄位]

class Inhfat5 {

  private int x = 7 ;

  char y = 'a' ;

  void inhmd( ) {

    System.out.println(y + "=" + x) ;

  }

}

 

class Inhson5 extends Inhfat5{

int z = 9 ;

}

 

class Inhmain5 {

  public static void main(String[ ] args) {

    Inhfat5 hhh = new Inhfat5( ) ;

    hhh.inhmd( ) ;//透過非private的方法可存取private成員x

    Inhson5 iii = new Inhson5( ) ;

    iii.inhmd( ) ;   //透過非private的方法可存取private成員x

  }

}

執行結果:C:\js>java Inhmain5

a=7

a=7

 

 

[21-6 final修飾子(final class)]

final是用來修飾欄位、方法與類別的修飾子。加上final修飾子的欄位,其值不可以被修改。加上final修飾子的方法,該方法不可以被覆寫。而加上final修飾子的類別,則不可以被繼承。

 

<final field範例>

加上final修飾子的欄位,其值不可以被修改。

class FinalField1{

  public static void main(String[] args){

   final int x = 10 ;     

    x = 29 ;                   //修改

 System.out.println("x=" + x) ;

  }

}

編譯結果:C:\js>javac FinalField1.java

FinalField1.java:4: error: cannot assign a value to final variable x

    x = 29 ;                    //修改

    ^

1 error

 

<final method範例>

加上final修飾子的方法,該方法不可以被覆寫。

 

class Finalfat1{

  int x = 10 ; 

final void finalmd1() {

  System.out.println("x=" + x) ;

  }

}

 

class Finalson1 extends Finalfat1 {

   void finalmd1() {                 //方法覆寫

    int x = 100 ;

    System.out.println("x的值為" + x) ;

  }

}

 

class Finalmain1{

  public static void main(String[] args){

    Finalson1 mmm = new Finalson1() ;

    mmm.x = 300;

    mmm.finalmd1() ;

  }

}

編譯結果:C:\js>javac Finalmain1.java

Finalmain1.java:9: error: finalmd1() in Finalson1 cannot override finalmd1() in

Finalfat1

  void finalmd1() {                  //方法覆寫

       ^

  overridden method is final

1 error

 

<final class範例>

加上final修飾子的類別,不可以被繼承。

 

final class Finalfat2{

  void finalmd3(){

  int y = 20 ;     

  System.out.println("y=" +y);

  }

}

 

class Finalson2 extends Finalfat2{ }   //不能被繼承

 

class Finalmain2{

   public static void main(String[] args){

   Finalson2 fc2 = new Finalson2();

   fc2.finalmd3();

  }

}

編譯結果:C:\js>javac Finalmain2.java

Finalmain2.java:8: error: cannot inherit from final Finalfat2

class Finalson2 extends Finalfat2{ }   //不能被繼承

                        ^

1 error

 

 

[21-7 super關鍵字]

super關鍵字可以引用父類別欄位、方法、建構式。

[格式]

父類別欄位:super.父類別欄位名。

父類別方法:super.父類別方法名。

父類別建構式:super()super(參數)

 

另以this關鍵字可以呼叫本身建構式。

[格式]

本身類別建構式:this()this(參數)

 

[21-7-1super關鍵字用於一般方法及方法內欄位時]

當父類別、子類別有相同之欄位、方法名稱,但其值或內容不同時,在子類別裡使用super關鍵字,可以參考(引用)父類別的欄位或方法。

<範例>

class Superfat1 {

  int x = 7 ;

  int y = 10 ;

  int tot ;

  void md1(int i, int j) {

      x = x * i ;

      y = y * j ;

     tot = x + y ; }  }

 

class Superson1 extends Superfat1 {

  int x = 14 ;

  int y = 20 ;

  void md2(int i, int j) {                        

    super.md1(i, j) ; //等同x = x * i ; y = y * j ;  tot = x + y ;

    System.out.println("總數=" + tot) ; }  }

 

class Supermain1 {

  public static void main(String[ ] args) {

     Superson1 nnn = new Superson1( ) ;

     nnn.md2(3,5) ; }  }

執行結果:C:\js>java Supermain1

總數=71

 

[21-7-2 super關鍵字在建構式的運用]

super()代表執行父類別的建構式。建構式呼叫另一建構式時,必須置於第一個敘述。

<範例>

class SuperClass1{

   SuperClass1(){

   System.out.println("super class(SuperClass1)建構式顯示此一訊息");

  }

  void superMethod1(){

     System.out.println("superMethod1");

  }

}

 

class SonClass1 extends SuperClass1{

  SonClass1(){

    super();     //執行父類別SuperClass1的建構式

    System.out.println("son class(SonClass1)建構式顯示此一訊息");

  }

  void sonMethod1(){

     System.out.println("sonMethod1");

  }

}

 

public class SuperMain11{

   public static void main(String[] args){

      SonClass1 son1 = new SonClass1();

      son1. sonMethod1();

  }

}

執行結果:C:\js>java SuperMain11

super class(SuperClass1)建構式顯示此一訊息

son class(SonClass1)建構式顯示此一訊息

sonMethod1

 

[21-7-3 super關鍵字在建構式多載的運用]

<範例>

class SuperClass2{

   SuperClass2(){

       System.out.println("super class(SuperClass2)建構式顯示此一訊息");

  }

  void superMethod2(){

      System.out.println("superMethod2");

  }

}

 

class SonClass2 extends SuperClass2{

   String str;

   SonClass2(String str){

  this();   //引用本身建構式

  this.str = str;

      System.out.println("son class(" + str + ")建構式顯示此一訊息");

  }

  SonClass2(){

     super();

  }

  void sonMethod2(){

     System.out.println("sonMethod2");

  }

}

 

public class SuperMain22{

   public static void main(String[] args){

       SonClass2 son2 = new SonClass2("SonClass2");

       son2. sonMethod2();

  }

}

執行結果:C:\js>java SuperMain22

super class(SuperClass2)建構式顯示此一訊息

son class(SonClass2)建構式顯示此一訊息

sonMethod2

 

 

[21-8 this關鍵字]

this關鍵字是指所屬類別欄位、建構式。

[格式]

所屬類別欄位:this.所屬類別欄位名。

所屬類別建構式:this ()this (參數)

 

[21-8-1所屬類別內欄位和this關鍵字]

所屬類別內之欄位應前置this關鍵字,但可省略。

 

[範例]用於一般方法內。

class This1a {

  String name ;

  int age ;

  void thismd1a(String x, int y) {

    this.name = x ; //前置this

    age = y ;       //省略this

    System.out.println(this.name + " " + age + "") ;

  }

}

class Thismain1a {

  public static void main(String[ ] args) {

    This1a sss = new This1a( ) ;

    sss.thismd1a("CKY",27) ; 

  }

}

執行結果:C:\js>java Thismain1a

CKY 27

 

[範例]用於建構式。

因建構式也是方法的一種,欄位的this使用方式和一般方法完全一樣。

class This1b {

  String name ;

  int age ;

  This1b(String x, int y) {

    this.name = x ; //前置this

    age = y ;       //省略this

    System.out.println(this.name + " " + age + "") ;

  }

}

classThismain1b {

  public static void main(String[ ] args) {

    This1b ttt = new This1b(" CTC",60) ;

    }

}

執行結果: C:\js>java Thismain1b

CTC 60

 

[範例]用於建構式多載。

當一個建構式呼叫另一個建構式時(建構式多載),必須置於該建構式第一個式子。故this()super()不能共存。

class This1c {

  String name ;

  int age ;

  This1c(String x) {this.name = x + "C" ;}

  This1c(String x, int y) {this(x); age = y; }

void thismd1c() {

   System.out.println(name + " " + age + "") ;

  }

}

 

class Thismain1c {

  public static void main(String[ ] args) {

    This1c uuu = new This1c("CT",60) ;

  }

}

執行結果:C:\js>java Thismain1b

CTC 60

 

[21-8-2欄位和區域變數同名]

欄位和區域變數同名時,前置this以資區別(視覺上的區別)

<無前置this>

class This2 {

  String name ;

  int age ;

  void thismd2(String name, int age) {

    name = name ; //無前置this

    age = age ;     //無前置this                                  

    System.out.println(name + " " + age + "") ;

  }

}

class Thismain2 {

  public static void main(String[ ] args) {

  this2 ttt = new this2( ) ;

  ttt.thismd2("CKS",32) ; 

  }

}

執行結果:C:\js>java Thismain2

CKS 32

 

 

<前置this>

class This3 {

  String name ;

  int age ;

  void thismd3(String name, int age) {

    this.name = name ; //前置this,左方為欄位,右方為區域變數(方法的參數)

    this.age = age ;     //前置this                                  

    System.out.println(name + " " + age + "") ;

  }

}

class Thismain3 {

  public static void main(String[ ] args) {

  This3 zzz = new This3( ) ;

  zzz.thismd3("CKS",32) ;

  }

}

執行結果:C:\js>java Thismain3

CKS 32

 

有無前置this,其效果相同,只是易於分辨。

arrow
arrow

    祈泊 發表在 痞客邦 留言(0) 人氣()