封裝
一般來說封裝就是將class用private隱藏內部資料, 並且以public方法提取/修改
簡單來說即屬性私有 get/set方法 符合高內聚低耦合的程式撰寫方式
最大程度只讓別人看到該看的東西, 剩下的東西全部包起來不給看
優點來說:
- 保護內部資料不被非法竄改取用
- 使用單一入口取用更改object之資料值
get/set方法可以在使用者輸入時做檢查是否合法之動作
class語法構造
public class Student{ //class屬性 private int age; private String name; //class方法 public void setAge(int a){ if(a>120 || a<0) this.age=10; else this.age=a; } public void setName(int n){ this.name=n; } }
顯示結果
public static void main(String[] args){ Student s1= new Student(); //new的當下即配置記憶體空間供object使用 s1.setName("N"); System.out.println(s1.getName()); //N }
建構子 constructor
當創立物件並且使用new這個關鍵字時,便表示我們分配記憶體空間供object使用,並且自動呼叫其class的constructor用來進行一些初始資料設定,此時才是真正的建立一個物件
constructor:
- 為和class名稱一樣的方法
必為public, 且無回傳型態和回傳值
public class Student{ //class屬性 private int age; private String name; //construtor public Student(int a,int n){ this.setAge(a); this.setName(n); } //class方法 public void setAge(int a){...} public void setName(int n){...} }
建構子有以下幾點必須注意:
- 如果class無constructor, 則會在new object時自動補上
public ClassName(){}
之建構子,不帶任何參數 - 如class有帶參數之constructor, class並不會自動生成無參數之constructor可使用,需要自己新增
- 如constructor中有引用父類別之super(),則必須在constructor方法中擺在第一行
- 如果class無constructor, 則會在new object時自動補上
繼承
原則上只要子類別以extends繼承父類別,就可以擁有父類別的方法和屬性
public subclass extends superclass
但是以下並不能繼承:
- 父類別的private方法和屬性 -->屬性使用父類別之get/set方法 方法沒救惹@@
- 父類的建構子 -->subclass方法中以
super(datatype1 v1,datatype2 v2)
方法使用 - 父類別static方法/屬性
- 父類別final屬性
Override / Overload
由於有很多繼承自父類別的方法並不適合子類別使用,子類別若想使用同名異式的方法,則需要覆寫(override)/隱藏(overload)
方法:
override: 與父類別物件方法同名,同回傳型態,同參數列
overload: 與父類別類別方法(static)同名,不一定同回傳型態,不一定同參數列
屬性:
override/overload: 只要名稱相同就行, 資料型態不一定
多型
當同一個名稱的method我們可以透過object的class差異而達到不同行為方式,也為一種同名異式
一個object的實際class是固定的,但是指向object的class操作指標可以改變
多型存在條件:
- 子類別繼承父類別並且發生override
- 以父類別指標操作子類別object
Father f1=new Son();
superclass & subclass
public class person{
public void say(){
System.out.println("Person!");
}
}
public class student extends person{
public void say(){ //override
System.out.println("Student!");
}
public void learn(){
System.out.println("Study!");
}
}
main code
public static void main(String args[]){
Student s1=new student();
person s2=new student();
s1.say(); //Student!
s1.learn(); //Study!
s2.say(); //Student! override讓父類別指標使用子物件的方法-->多型
s2.learn(); //Error 父類指標不能引用子類物件中擴充的功能
((student)s2).learn(); //Study! 強制轉型使用子類物件擴充功能
}
多型雖然可以用父類指標操作子類物件,但是不能操作那些子類自己另外擴充的方法或是屬性,在此我們必須提到物件等級特性:
class等級排序: supercalss > subclass
class內容多寡: subclass > superclass
可以用較高等級排序的class指標操作較低等級排序的class object(也可以相反
這種操作方式稱為參考(instanceof)
A類別指標 參考 B物件實際class 來操作object
多型則是為: 父類別指標 參考 子類別實際class 來操作object
物件轉型
但是其中有擴充的內容superclass指標卻不能操作
e.g. Father f1=new Son();
f1不能操作 Son()的擴充功能
這時便要用到物件轉型觀念:
注意object是用操作自己的class指標去相比較等級
- 向上轉型: object採用父類class指標操作 會丟失已擴充方法
student obj=new student(); person p=student; //student-->person
- 向下轉型: object採用子類class指標操作 需要強制轉型 會增加擴充方法
<各人總結>person obj=new student(); student s=(student) obj; //強制轉型 person-->student
向上向下使用操作此object的class指標變化來決定
向上轉型代表會缺少一些擴充function 之接轉換切除用不到強制轉型
向下轉型代表會多一些擴充function可以用 因此要強制轉型擴充一下空間
參考 instanceof
A類別指標 參考 B物件實際class 來操作object,稱此為參考
if(A instanceof B)
會回傳true/false
true表示A B物件之間有繼承的上下關係,A物件為B物件的父類或同類,可以用其class指標操作B類物件
同場加映
abstract 抽象
子類override代表父類方法不適用, 則我們可以創立沒有內容的抽象概念框架,再由子類去繼承後實作出來
抽象class特色:
- 無法new物件,只能參考子類別物件new object
- 抽象class中可以有普通方法
- 一旦class中有抽象方法, 此class必為抽象class
public abstract class Action{
public abstract void dosomething(); //抽象方法 子類別必須規範好方法實作內容
public void realaction(){...} //一般方法
}
interface 介面
將框架及實作徹底分離,實作的類別要將方法全部實作出來
介面特性:
- 方法只有abstract方法
- 不能以interface new object出來
- 實作類別以 implements 實作interface的內容, 可以implements多個interface
public interface UserService{ void add(string name); //默認是abstract function void delete(string name); //默認是abstract function }
public class user implements UserService{
void add(string name){...}
void delete(string name){...}
}