# JAVA 繼承
###### tags: `Java`
---
* 子類別繼承父類別,使用關鍵字【extends】
* 可以有很多個父類別,垂直繼承
:::success
舉例程式碼:
:::spoiler
```java=
package Ex11.MoreExtendDemo;
/**多重繼承,爸爸的爸爸的爸爸~無限循環XD**/
//class 父類別
class CMath {
public void getMax(int a, int b){
int bigNum;
if(a>b)
bigNum=a;
else
bigNum=b;
System.out.println(a+ "與" +b+ "的最大數為" +bigNum);
}
}
//class 子類別
class SonCMath extends CMath { //SonCMath繼承父類別CMath
public void getFactorial(int a){
int ans = 1, i;
System.out.print(a+ "! = ");
for (i=1;i<a;i++){
System.out.print(i+ "*");
ans *=i;
}
ans *= a;
System.out.println(a+ " = " +ans);
}
}
class GrandSonCMath extends SonCMath {
public void getFabonacci(int a){
int firstNum = 0, secondNum = 1;
System.out.println("費氏數列:" +firstNum+ ", " +secondNum);
int ans;
for(int i=2;i<=a; i++){
ans = firstNum = secondNum;
System.out.print(", " +ans);
firstNum = secondNum;
secondNum = ans;
}
}
}
//主程式
public class MoreExtendDemo {
public static void main(String[] args) {
GrandSonCMath math2 = new GrandSonCMath();
math2.getMax(10,20); //呼叫繼承祖父類別的方法
math2.getFactorial(5); //呼叫繼承父親的方法
math2.getFabonacci(10); //呼叫子類別的方法
}
}
```
:::
---
## Override 複寫
當使用到這個方法時,子類別的方法會覆蓋掉父類別同名稱的方法,也就是說程式會選擇子類別的方法來執行。
:::success
舉例 Override 程式碼:
:::spoiler
```java=
package Ex11.OverrideDemo;
//class 父類別
class CMath {
public void getMax(int a, int b){
int bigNum;
if(a>b)
bigNum=a;
else
bigNum=b;
System.out.println(a+ "與" +b+ "的最大數為" +bigNum);
}
}
//class 子類別
class SonCMath extends CMath { //SonCMath繼承父類別CMath
public void getMax(int a, int b){
if(a>b){
System.out.println(a+ "和" +b+ "的最大數為" +a);
}else if(a<b){
System.out.println(a+ "和" +b+ "的最大數為" +b);
}else{
System.out.println(a+ "和" +b+ "一樣大");
}
}
}
//主程式
public class OverricdDemo {
public static void main(String[] args) {
CMath math3 = new CMath();
math3.getMax(20, 20); //使用父類別的方法
SonCMath math4 = new SonCMath();
math4.getMax(20, 20); //子類別覆蓋了父類別的方法
}
}
```
:::
---
## 預設建構式
* 就是建立好繼承的class,裡面的程式會預設執行
* 依序由最頂層的父層開始執行(年紀最大的長輩說話子孫都要聽XD)
:::success
舉例 預設建構式 程式碼:
:::spoiler
```java=
package Ex11.constructorExtend;
//預設建構式(會預設執行的程式,由最上層的類別先執行
//祖父層
class CMath {
protected int a = 1;
CMath(){
System.out.println("a = " +a);
}
}
//父層
class SonCMath extends CMath {
protected int b = 2;
SonCMath(){
System.out.println("a+b=" +(a+b));
}
}
//子類別
class GrandSonCMath extends SonCMath {
protected int c = 4;
GrandSonCMath(){
System.out.println("a+b+c=" +(a+b+c));
}
}
//主程式
public class ConstructorExtend {
public static void main(String[] args) {
new GrandSonCMath(); //執行子類別,又因為子類別繼承了父層與祖父層,
// 所以會預設自動執行繼承內的程式
}
}
```
:::
---
## Final
* 當使用final來宣告一個常數時,記得一定要同時給予這個常數初值(常數的值不能被變更的)
* final如果應用在方法成員上,就表示這個方法不可以被子類別覆寫。
* 如果在class之前加上final時,則表示該類別無法被繼承。
:::success
舉例 Final 程式碼:
:::spoiler
```java=
package Ex11.Final;
//當使用final來宣告一個常數時,記得一定要同時給予這個常數初值(常數的值不能被變更的)
//final如果應用在方法成員上,就表示這個方法不可以被子類別覆寫。
//如果在class之前加上final時,則表示該類別無法被繼承。
final class Cdog { //無法被繼承
int weight;
}
class Ccar {
//private final int speed; //這樣寫是錯的,要給初始值
private final int speed = 120;
public final void showBigSpeed(String s){
System.out.println(s+ "最大速度是" +speed+ "公里!");
}
}
class PiliCcar extends Ccar {
/*父類別showBigSpeed方法有設定final,所以子類別無法覆寫
public void showBigSpeed(String s){
System.out.println(s+ "最大速度是" +speed+ "公里!");
}
*/
}
public class FinalDemo1 {
public static void main(String[] args) {
Ccar car1 = new Ccar();
car1.showBigSpeed("car1");
PiliCcar car2 = new PiliCcar();
car2.showBigSpeed("car2");
}
}
```
:::
---
## Static 的限制
* static方法成員只可以使用static資料成員,和呼叫static方法成員。
* 父類別如有設定static方法,子類別不能使用相同的static方法(不可覆寫)
---
## abstract抽象
* abstract關鍵字宣告
* 抽象方法必須用abstract關鍵字宣告,其修飾子不能為private
* 抽象類別被子類別繼承後,其抽象方法必須被子類別覆寫(override)。即子類別必須重新定義該抽象方法,且方法內要有實作敘述區段,如此抽象方法方能具體化。
* 抽象類別無法建立物件實體,其建構式與一般方法成員若要由子類別來呼叫,則須使用super()敘述來呼叫。
:::success
舉例 abstract 程式碼:
:::spoiler
```java=
package Ex11.AbstractDemo;
abstract class Ccar {
int speed;
public abstract void addSpeed(int s);
public static void showData(){
System.out.println("所有車子都可以加速!!\n");
}
}
class PiliCar extends Ccar {
public void addSpeed(int s){
System.out.println("霹靂車目前速度:" +speed);
speed += s;
System.out.println("霹靂車 加速後:" +speed);
}
}
//繼承抽象類別Ccar,必須實作Ccar類別的addSpeed的抽象方法
class BMWCar extends Ccar {
public void addSpeed(int s){
System.out.println("BMW目前速度" +speed);
speed += s;
if (speed <= 200){
System.out.println("BMW 加速後:" +speed);
}else{
System.out.println("BMW最大速度 200 無法再加速了");
}
}
}
//主程式
public class AbstractDemo {
public static void main(String[] args) {
Ccar.showData(); //呼叫Ccar抽象類別的showData()靜態方法
PiliCar car1 = new PiliCar();
car1.addSpeed(150);
car1.addSpeed(120);
System.out.println();
BMWCar car2 = new BMWCar();
car1.addSpeed(150);
car1.addSpeed(120);
// Ccar car3 = new Ccar(); //出現錯誤,抽象類別無法產生實體
}
}
```
:::
---
## Interface 介面
* 定義介面的時候,必須使用保留字interface,方法內的主體一定是空的程式碼
* 引用的資料成員則必須給予初值,實作介面必須使用implements保留字


---
## Interface & extends 介面繼承
:::success
舉例 介面繼承 程式碼:
:::spoiler
```java=
package Ex11.InterFaceDemo2;
interface IMove {
public void showSpeed();
}
interface IFly {
public void showFly();
}
interface IAnimal extends IMove, IFly { //IAnimal 介面繼承IMove, IFly
public void showAttack();
}
class CAirPlane implements IMove, IFly { //實作IMove, IFly 介面
public void showSpeed(){
System.out.println("飛機每一次加速,會增加20公里!");
}
public void showFly(){
System.out.println("飛機的最快移動方式,就是飛行!");
}
}
//實作IAnimal介面,因為IAnimal繼承了IMove, IFly ,所以方法有三個
class CSitrYaMan implements IAnimal {
public void showSpeed(){
System.out.println("賽亞人每一次加速,會增加30公里!");
}
public void showFly(){
System.out.println("賽亞人飛的速度比光速還快!");
}
public void showAttack(){
System.out.println("賽亞人攻擊會使用龜派氣功!");
}
}
//主程式
public class InterFaceDemo2 {
public static void main(String[] args) {
CAirPlane air1 = new CAirPlane(); //用CAirPlane建立air1物件
air1.showSpeed();
air1.showFly();
System.out.println();
CSitrYaMan man1 = new CSitrYaMan(); //把class CSitrYaMan製作成物件man1
man1.showSpeed();
man1.showFly();
man1.showAttack();
}
}
```
:::
:::warning
小知識: \t 在同一个缓冲区内横向跳8个空格
:::
---
## 以介面實作多型
* 子類別已繼承父類別,即無法再繼承抽象類別(Java為單一繼承)
* 使用介面來達成多型,透過介面來達成多型的寫法和抽象類別大同小異。
---
## 套件繼承
* 引用不同套件需在最上方宣告<span class="code1">import 某某package名稱;</span>
* 可以import 多個套件的類別。


:::success
舉例 套件繼承關係 程式碼:
:::spoiler
```java=
package Ex11.SelfPackage;
import Ex11.OtherPackage.Other; //引用外部Package
public class Self {
public static void main(String[] args) {
//同一套件(The same package)
Another obj_a = new Another();
obj_a.show_a(); //預設default (繼承:可 , 使用:可)
obj_a.show_b(); //public (繼承:可 , 使用:可)
obj_a.show_c(); //protected (繼承:可 , 使用:可)
//obj_a.show_d(); //private (繼承:不行 , 使用:不行)
System.out.println();
//不同套件(different package)
Other obj_o = new Other();
//obj_o.show_a(); //預設default (繼承:不行 , 使用:不行)
obj_o.show_b(); //public (繼承:可 , 使用:可)
//obj_o.show_c(); //protected (繼承:可 , 使用:不行)
//obj_o.show_d(); //private (繼承:不行 , 使用:不行)
}
}
```
:::
---
<!--
:::success
舉例程式碼:
:::spoiler
```java=
```
:::
-->
---
<span class="code1"></span>
<style>
h2 {
color: #2383B8;
}
h3 {
color: #1AA340;
}
h4 {
color: white;
background-color: #2383B8;
padding:8px;
}
.code1 {
padding: 2px 4px;
font-size: 90%;
color: #c7254e;
background-color: #f9f2f4;
border-radius: 4px;
font-family:'Fira Code';
}
.code {
padding: 2px 4px;
font-size: 90%;
font-family:'Fira Code';
}
</style>