# 2019/0520/繼承&存取權特性+java作業四+字符串格式化+多形+抽象類別

前情提要&#x20;繼承特性
----------

類別變數改為protected 保護

就不用用方法存取變數

但壞處就是沒辦法用商業邏輯驗證變數

且子類父類會相依性提高

## 存取權 & 繼承特性

#### 接著實作CommissionEmployeeExtV3&#xD;

![](https://1902678905-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LVJQfuBXyvHwCd1Nadk%2F-LfOuQEFLAXyFii0i8_v%2F-LfP1pUY2IQ2qZ_rX7TL%2Fimage.png?alt=media\&token=2ec1d1cc-f7a7-44d8-ab88-fc088809694c)

![](https://1902678905-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LVJQfuBXyvHwCd1Nadk%2F-LfOuQEFLAXyFii0i8_v%2F-LfP1tdEnBeYJN4PdPcE%2Fimage.png?alt=media\&token=82371313-9308-40c9-a7e9-23c4e95ec870)

可以跟V2比較

把V2變數改為

然後需要變數屬性的部分都運存取方法得到

![](https://1902678905-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LVJQfuBXyvHwCd1Nadk%2F-LfOuQEFLAXyFii0i8_v%2F-LfP2OonkeLzh6-Axwd4%2Fimage.png?alt=media\&token=ebef5d5f-ad6a-4300-b7f9-aa08adc91f89)

維護修改的範圍限制在建構式與存取方法

![](https://1902678905-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LVJQfuBXyvHwCd1Nadk%2F-LfOuQEFLAXyFii0i8_v%2F-LfP2deVQgm-Dhv8dIT_%2Fimage.png?alt=media\&token=ad63e9e4-b557-488d-8f0c-1f7bc619d242)

用呼叫的就會達到上述維護修改範圍限制的好處

super() 是一種連鎖方法 能夠呼叫直接父類別的建構式

才能在子類別繼續執行變數檢查等等的內容

Google search java se 8 object

{% embed url="<https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html>" %}

新增一個CommissionEmployeeExtV3Test 測試V3改完後功能是否正常

#### ###BasePlusCommissionEmployeeExtV3.java&#xD;

```
package com.example.java;

public class BasePlusCommissionEmployeeExtV3 extends CommissionEmployeeExtV3 {

	private double baseSalary; // 底薪

	public BasePlusCommissionEmployeeExtV3(String firstName, String lastName, String idNumber, double grossSales,double commissionRate, double baseSalary) {
		super(firstName, lastName, idNumber, grossSales, commissionRate);

		if (baseSalary < 0.0)
			throw new IllegalArgumentException("底薪金額必須 >= 0.0");

		this.baseSalary = baseSalary;
	}

	public void setBaseSalary(double baseSalary) {
		if (baseSalary < 0.0)
			throw new IllegalArgumentException("底薪金額必須 >= 0.0");

		this.baseSalary = baseSalary;
	}

	public double getBaseSalary() {
		return baseSalary;
	}

	@Override
	public double earnings() {
//		grossSales = -5000.0;
		return getBaseSalary() + (super.getCommissionRate() * super.getGrossSales());
	}

	@Override
	public String toString() {
	      return String.format("%s %n %s: %.2f" ,    
	 	         super.toString(),
	 	         "底薪金額", getBaseSalary());
	}

}

```

#### ###BasePlusCommissionEmployeeTestExtV3.java&#xD; ???

```
檔案不確定有沒有上傳但其實就是測試以上類別的方法 set 與get
```

### #繼承設計類別總結&#xD;

特殊性邏輯往子類丟

通用性邏輯往父類丟

![](https://1902678905-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LVJQfuBXyvHwCd1Nadk%2F-LfOuQEFLAXyFii0i8_v%2F-LfP3nBFZe0Z9WywwPBx%2Fimage.png?alt=media\&token=75132725-7bef-4d66-b9b5-1d472cd877c5)

#### ##作業四

![](https://1902678905-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LVJQfuBXyvHwCd1Nadk%2F-LfOuQEFLAXyFii0i8_v%2F-LfP92roVSGfi1f08Vdq%2Fimage.png?alt=media\&token=721c0d45-7ab7-4ae8-8e5a-9f9169a3d05f)

\#作業四 繼承特性
------

#### ###Shape.java&#xD;

```
package com.example.java;

//實作Shape形狀類別

//公開存取 繼承於 Class Object 
//https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
public class Shape extends Object {
//私有存取 雙精度浮點數 double 型態變數表示 area 面積
	private double area;
//公開存取 shape(無參數) 建構子 
//this指建構式自身
//https://developer.mozilla.org/zh-TW/docs/Web/JavaScript/Reference/Operators/this
//https://openhome.cc/Gossip/Java/This.html
//http://peimei0808.pixnet.net/blog/post/125557313-%5Bjava%5D-java%E4%B8%AD%E5%A6%82%E4%BD%95%E4%BD%BF%E7%94%A8%E3%80%8Cthis%E3%80%8D%E5%8F%8A%E5%85%B6%E5%8A%9F%E7%94%A8%E4%B9%8B%E4%BB%8B%E7%B4%B9
	public Shape() {
		this.area = 0;
	}
//公開存取 shape(double型態area參數) 建構式
//當area參數小於0時拋出錯誤訊息物件參數為 "面積必須 >=0"
	public Shape(double area) {
		if (area < 0)
			throw new IllegalArgumentException("面積必須  >= 0");
		this.area = area;
	}
//公開存取 反傳值double型態 getArea(無參數) 方法
//回傳 area變數
	public double getArea() {
		return area;
	}
//公開存取 沒有反傳值 getArea(double型態area參數) 方法
//當area參數小於0時拋出錯誤訊息物件參數為 "面積必須 >=0"
	public void setArea(double area) {
		if (area < 0)
			throw new IllegalArgumentException("\"面積必須為大於或等於0\"");
		this.area = area;
	}

//覆載Override object.toString 靜態類別方法
//https://wayne265265.pixnet.net/blog/post/115533452-%E3%80%90%E6%95%99%E5%AD%B8%E3%80%91override-%E8%88%87-overload-%E7%9A%84%E5%B7%AE%E5%88%A5
//%s : %.2f%n 為字符串格式
	@Override
	public String toString() {
		return String.format("%s : %.2f%n", "此形狀的面積為", getArea());
	}

}

```

#### ###Rectangle.java

```
package com.example.java;
//實作Rectangle長方形類別

//公開存取 繼承於 Class Shape
public class Rectangle extends Shape {
//私有存取 雙精度浮點數 double 型態變數 表示 length 長度
//私有存取 雙精度浮點數 double 型態變數 表示 width 寬度
	private double length;
	private double width;
	
//公開存取 shape(double型態length長度, double型態width寬度) 建構子 
//當Rectangle的參數小於0時拋出錯誤訊息物件參數為"長度 、寬度皆必須大於等於0"
//並將建構式帶入的參數指給私有存取的域外變數
	public Rectangle(double length, double width) {
		if ((length < 0) || (width < 0))
			throw new IllegalArgumentException("長度 、寬度皆必須大於等於0");
		this.length = length;
		this.width = width;
		ComputeArea();
	}
//公開存取 double型態反傳值  getLength(無參數) 方法
	public double getLength() {
		return length;
	}
//公開存取 無反傳值 setLength(double型態length參數) 方法
//當長度小於零時反傳"長度必須大於等於 0"
	public void setLength(double length) {
		if (length < 0)
			throw new IllegalArgumentException("長度必須大於等於 0");
		this.length = length;
	}
//公開存取 double型態反傳值 getWidth(無參數) 方法
	public double getWidth() {
		return width;
	}
//公開存取 無反傳值 setWidth(double型態width參數) 方法
//當長度小於零時反傳"寬度必須大於 0"
	public void setWidth(double width) {
		if (width < 0)
			throw new IllegalArgumentException("寬度必須大於 0");
		this.width = width;
	}
//公開存取 double型態反傳值 ComputeArea(無參數) 方法
//用getLength方法取得長度與getWidth方法取得寬度做*乘法運算將運算值傳入直接父輩方法super.setArea中
	public double ComputeArea() {
		super.setArea(getLength() * getWidth());
		return getArea();
	}
//覆載
	@Override
	public String toString() 
	{
		return String .format("%s : %.2f%n","形狀為矩形，面積為",getArea() );
	}
}

```

#### ###Triangle.java

```
package com.example.java;
//實作Triangle三角形類別

//公開存取 繼承於 Class Shape
public class Triangle extends Shape {
//私有存取 雙精度浮點數 double 型態變數 表示 base 底邊長度
//私有存取 雙精度浮點數 double 型態變數 表示 height 高度
	private double base;
	private double height;

//公開存取 Triangle(double型態base底邊長度, double型態height高度) 建構子 
//當Triangle的參數小於0時拋出錯誤訊息物件參數為"底邊 、高度皆必須大於等於0"
//並將建構式帶入的參數指給私有存取的域外變數
	public Triangle(double base, double height) {
		if ((base < 0) || (height < 0))
			throw new IllegalArgumentException("底邊 、高度皆必須大於等於0");
		this.base = base;
		this.height = height;
		ComputeArea();
	}
//公開存取 double型態反傳值  getBase(無參數) 方法
	public double getBase() {
		return base;
	}
//公開存取 無反傳值 setBase(double型態base參數) 方法
//當長度小於零時反傳"底邊必須大於0"
	public void setBase(double base) {
		if (base < 0)
			throw new IllegalArgumentException("底邊必須大於0");
		this.base = base;
	}
//公開存取 double型態反傳值 getHeight(無參數) 方法
	public double getHeight() {
		return height;
	}
//公開存取 無反傳值 getHeight(double型態height參數) 方法
//當長度小於零時反傳"高度必須大於等於0"
	public void getHeight(double height) {
		if (height < 0)
			throw new IllegalArgumentException("高度必須大於等於0");
		this.height = height;
	}
//公開存取 double型態反傳值 ComputeArea(無參數) 方法
//用getBase方法取得底邊長度與getHeight方法取得高度做*乘法後除與2運算將運算值傳入直接父輩方法super.setArea中
	public double ComputeArea() {
		setArea(getBase() * getHeight() / 2);
		return getArea();
	}
//覆載
	@Override
	public String toString() 
	{
		return String .format("%s : %.2f%n","形狀為三角形，面積為",getArea() );
	}
}

```

Hw4Test.java ( 使用上述類別與方法 且有多型?

宣告物件變數 建構式初始化時順便給予參數

接著印出

接著宣告一個物件陣列塞剛剛的物件進去

For印不同參數版本的物件值出來

#### ###Hw4Test.java

```
package com.example.java;
import com.example.java.Shape;

public class Hw4Test {

	public static void main(String[] args) {
		// TODO 自動產生的方法 Stub
		
//建構三個物件並給予參數
		Shape sp1 = new Shape(11);
		Rectangle rt1 = new Rectangle(6,0);
		Triangle ta1 = new Triangle(6, 5.0);
//利用物件使用方法並給予參數
		sp1.setArea(5);
//		rt1.ComputeArea();
//利用靜態方法印出以上物件
		System.out.println(sp1);
		System.out.println(rt1);
		System.out.println(ta1);
		
		
//      以下為多型示範 ( 結果如同以上 )
		
//		Shape[] shapeArray = new Shape[3];
//		shapeArray[0] = sp1;
//		shapeArray[1] = rt1;
//		shapeArray[2] = ta1;
//		
//		for(int i=0;i<shapeArray.length;i++)
//		{
//			System.out.println(shapeArray[i]);
//		}
	}

}

```

\#字符串格式化字符串函数

<https://ctf-wiki.github.io/ctf-wiki/pwn/linux/fmtstr/fmtstr\\_intro/>

<https://www.google.com/search?q=java+tostring+%E6%A0%BC%E6%98%AF\\&oq=java+tostring+%E6%A0%BC%E6%98%AF\\&aqs=chrome..69i57.9777j0j4\\&sourceid=chrome\\&ie=UTF-8>

## #多型

![](https://1902678905-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LVJQfuBXyvHwCd1Nadk%2F-LfOuQEFLAXyFii0i8_v%2F-LfPANmrG-8SNRe4zxDJ%2Fimage.png?alt=media\&token=cc6ba5ca-a2d8-4fff-8213-d585c5be91dd)

雇員更上層的父類別?

![](https://1902678905-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LVJQfuBXyvHwCd1Nadk%2F-LfOuQEFLAXyFii0i8_v%2F-LfPAT2x8xMgwRJ-wpph%2Fimage.png?alt=media\&token=6ce09fe4-06fa-4e55-afd7-30eb6c475a30)

#### ##擴充性&#xD;

直接間接處理相同父類別的物件

![](https://1902678905-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LVJQfuBXyvHwCd1Nadk%2F-LfOuQEFLAXyFii0i8_v%2F-LfPAYvnK5VPXb8LQ62R%2Fimage.png?alt=media\&token=fa9f57ab-75b2-4733-bd7c-331a92b42815)

![](https://1902678905-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LVJQfuBXyvHwCd1Nadk%2F-LfOuQEFLAXyFii0i8_v%2F-LfPAbwJh62qosVEluPj%2Fimage.png?alt=media\&token=86238f75-4b11-44f9-835c-523317980152)

子可以參考父但父不可參考子

子類別物件可以拿去父用

![](https://1902678905-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LVJQfuBXyvHwCd1Nadk%2F-LfOuQEFLAXyFii0i8_v%2F-LfPApr3voC74YDJQALR%2Fimage.png?alt=media\&token=ad23925d-7bc0-42a7-8d8b-22c60375f44e)

但父不可以參考子 除非向下轉型 ( 整數轉換成浮點數

![](https://1902678905-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LVJQfuBXyvHwCd1Nadk%2F-LfOuQEFLAXyFii0i8_v%2F-LfPAxvPE7jLAmH2wwHg%2Fimage.png?alt=media\&token=92e3eabf-72d4-4964-84e2-bf733aad3d74)

強制型別轉換 向下轉型 父轉子 在塞到子類別物件變數

得到呼叫子類別方法能力

子類別是一種父類別 但父類別不是一種子類別

![](https://1902678905-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LVJQfuBXyvHwCd1Nadk%2F-LfOuQEFLAXyFii0i8_v%2F-LfPB3MKkC0dKZL8dHqG%2Fimage.png?alt=media\&token=23c10ba1-5b80-464b-9782-73885c04eae0)

一個父類別有很多個子類別的話，會呼叫出正確的版本ex

xxxx.toString()

不會呼叫到

Object.toString

### ##接著實作剛剛看到的觀念由以下幾個實例&#xD;

#### ###CommissionEmployee.java&#xD;

```
package polymorphism;

public class CommissionEmployee extends Object{
	
	   private final String firstName;                        
	   private final String lastName;                         
	   private final String idNumber;             
	   private double grossSales; 
	   private double commissionRate; // 佣金，抽庸的比例
	                                
	   public CommissionEmployee(String firstName, String lastName, String idNumber, double grossSales, double commissionRate)
	   {                                                                  
	      super();
		   
		  if (grossSales < 0.0) 
	         throw new IllegalArgumentException("銷售金額必須 >= 0.0");

	      if (commissionRate <= 0.0 || commissionRate >= 1.0)
	         throw new IllegalArgumentException("佣金比例必須 > 0.0 and < 1.0");

	      this.firstName = firstName;                                     
	      this.lastName = lastName;                                    
	      this.idNumber = idNumber;         
	      this.grossSales = grossSales;
	      this.commissionRate = commissionRate;
	   } 

	   public String getFirstName()
	   {
	      return firstName;
	   }

	   public String getLastName()
	   {
	      return lastName;
	   } 

	   public String getIdNumber()
	   {
	      return idNumber;
	   } 

	   public void setGrossSales(double grossSales)
	   {
	      if (grossSales < 0.0) 
	         throw new IllegalArgumentException("銷售金額必須 >= 0.0");

	      this.grossSales = grossSales;
	   } 

	   public double getGrossSales()
	   {
	      return grossSales;
	   } 

	   public void setCommissionRate(double commissionRate)
	   {
	      if (commissionRate <= 0.0 || commissionRate >= 1.0)
	         throw new IllegalArgumentException("佣金比例必須 > 0.0 and < 1.0");

	      this.commissionRate = commissionRate;
	   } 

	   public double getCommissionRate()
	   {
	      return commissionRate;
	   } 
	        
	   public double earnings()              
	   {                                     
	      return getCommissionRate() * getGrossSales();
	   } 

	   @Override
	   public String toString()                                             
	   {                                                                    
	      return String.format("%s: %s %s%n%s: %s%n%s: %.2f%n%s: %.2f %n%s: %.2f" ,    
	         "領佣金的員工姓名", getFirstName(), getLastName(),                    
	         "身分證字號", getIdNumber(),                
	         "每周銷售金額", getGrossSales(),                                     
	         "佣金比例", getCommissionRate(),
	         "總佣金",getCommissionRate() * getGrossSales());                           
	   } 

}

```

#### ###BasePlusCommissionEmployee.java

```
package polymorphism;

public class BasePlusCommissionEmployee extends CommissionEmployee {

	private double baseSalary; // 底薪

	public BasePlusCommissionEmployee(String firstName, String lastName, String idNumber, double grossSales,double commissionRate, double baseSalary) {
		super(firstName, lastName, idNumber, grossSales, commissionRate);

		if (baseSalary < 0.0)
			throw new IllegalArgumentException("底薪金額必須 >= 0.0");

		this.baseSalary = baseSalary;
	}

	public void setBaseSalary(double baseSalary) {
		if (baseSalary < 0.0)
			throw new IllegalArgumentException("底薪金額必須 >= 0.0");

		this.baseSalary = baseSalary;
	}

	public double getBaseSalary() {
		return baseSalary;
	}

	@Override
	public double earnings() {
//		grossSales = -5000.0;
		return getBaseSalary() + (super.getCommissionRate() * super.getGrossSales());
	}

	@Override
	public String toString() {
	      return String.format("%s %n %s: %.2f" ,    
	 	         super.toString(),
	 	         "底薪金額", getBaseSalary());
	}

}

```

#### ###WeekSalaryPlusCommissionEmployee

```
package polymorphism;

public class WeekSalaryPlusCommissionEmployee extends CommissionEmployee {

	private double weekSalary; // 周薪

	public WeekSalaryPlusCommissionEmployee(String firstName, String lastName, String idNumber, double grossSales,double commissionRate, double weekSalary) {
		super(firstName, lastName, idNumber, grossSales, commissionRate);

		if (weekSalary < 0.0)
			throw new IllegalArgumentException("周薪金額必須 >= 0.0");

		this.weekSalary = weekSalary;
	}

	public void setWeekSalary(double weekSalary) {
		if (weekSalary < 0.0)
			throw new IllegalArgumentException("周薪金額必須 >= 0.0");

		this.weekSalary = weekSalary;
	}

	public double getWeekSalary() {
		return weekSalary;
	}

	@Override
	public double earnings() {
		return getWeekSalary() + (super.getCommissionRate() * super.getGrossSales());
	}

	@Override
	public String toString() {
	      return String.format("%s%n %s %n %s: %.2f" , "領周薪加獎金的員工",   
	 	         super.toString(),  "周薪金額", getWeekSalary() );
	}

}

```

#### ###PolymorphismTest.java

```
package polymorphism;

public class PolymorphismTest {

	public static void main(String[] args) {
		// TODO 自動產生的方法 Stub

//		BasePlusCommissionEmployee employee01 = new BasePlusCommissionEmployee("劉", "德華", "A123456789", 10000, .06,1000);
//		CommissionEmployee employee02 = new CommissionEmployee("陳", "立農", "A123456789", 5000, .1);
//		CommissionEmployee employee03 = new CommissionEmployee("周", "子瑜", "A111111111", 6000, .06);
//		BasePlusCommissionEmployee employee04 = new BasePlusCommissionEmployee ("吳", "奕帆", "A222222222", 1000, .08,5000);
//		
//		System.out.printf("%n%s:%n%n%s%n", "第 1 位員工薪資資料", employee01.toString());
//		System.out.printf("%n%s:%n%n%s%n", "第 2 位員工薪資資料", employee02.toString());
//		System.out.printf("%n%s:%n%n%s%n", "第 3 位員工薪資資料", employee03.toString());
//		System.out.printf("%n%s:%n%n%s%n", "第 4 位員工薪資資料", employee04.toString());

		CommissionEmployee employeeArray[] = new CommissionEmployee[5];
		employeeArray[0] = new BasePlusCommissionEmployee("劉", "德華", "A123456789", 10000, .06, 1000);
		employeeArray[1] = new CommissionEmployee("陳", "立農", "A123456789", 5000, .1);
		employeeArray[2] = new CommissionEmployee("周", "子瑜", "A111111111", 6000, .06);
		employeeArray[3] = new BasePlusCommissionEmployee("吳", "奕帆", "A222222222", 1000, .08, 5000);
		employeeArray[4] = new WeekSalaryPlusCommissionEmployee("韓", "國魚", "A333333333", 2000, .05, 500);
		
		for(int i = 0; i < employeeArray.length ;i++)
		{
			System.out.printf("%n%s%d%s:%n%n%s%n", "第 ",i+1," 位員工薪資資料", employeeArray[i].toString());		
		}

	}

}

```

父類別子用與多參數型

就算再設計設備的時候也要考慮未來可能擴充元件與特定控制方法，所以一定要有多型，ex 薪水計算方法現行公司指有兩種，難道未來不會有別種或是更多種?

\#抽象類別 ( 繼承階層的提升?&#x20;( 待補下級待續
--------------

指拿來定義 無法用new配置實體物件

![](https://1902678905-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LVJQfuBXyvHwCd1Nadk%2F-LfOuQEFLAXyFii0i8_v%2F-LfPB_J5HqkjTDKhBpU4%2Fimage.png?alt=media\&token=e61147c1-4fbe-4229-a694-39e007c9a41f)

抽象類別的 子類別一定要實作屬於子類別版本的方法

讓子符合父的一定規範

![](https://1902678905-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LVJQfuBXyvHwCd1Nadk%2F-LfOuQEFLAXyFii0i8_v%2F-LfPBdIRCO9hWY9D3sTd%2Fimage.png?alt=media\&token=10676871-ab28-4485-a6ae-b2d1df4fbe26)

規範架構 擴展的範圍
