在Java編程的世界里,封裝、繼承和多態是面向對象編程(OOP)的三大基石,它們支撐起整個Java程序設計的骨架,讓代碼更加靈活、可擴展和易于維護。
接下來,我會用一種輕松的方式,并通過一個貼近生活的例子來展示它們是如何協同工作的。
封裝(Encapsulation)
封裝,簡單來說,就是把對象的內部狀態(屬性)和行為(方法)包裝在一起,并對外界隱藏其內部實現細節的過程。
想象一下你正在使用一臺手機,你并不需要知道手機內部的電路板是如何布局的,也不必了解操作系統是如何管理各個應用的,你只需知道按哪個按鈕可以打電話、哪個圖標能打開相機。
手機的設計者通過按鈕、屏幕和菜單等界面,將復雜的內部結構封裝了起來,讓你可以方便地使用手機的各項功能,這就是封裝的思想。
在Java中,我們使用訪問修飾符(如private、protected、public)來控制類的成員(屬性和方法)的可見性,以此實現封裝。
通常,我們會將屬性設為私有(private),并通過公共(public)的方法來操作這些屬性,這些方法被稱為getter和setter。
例子:假設我們有一個簡單的BankAccount類,封裝了賬戶余額這一敏感信息。
1public class BankAccount {
2 private double balance; // 私有屬性,封裝了賬戶余額
3
4 // Getter方法,外部可以通過這個方法獲取余額
5 public double getBalance() {
6 return balance;
7 }
8
9 // Setter方法,外部可以通過這個方法設置余額,但這里可以加入余額校驗邏輯
10 public void setBalance(double amount) {
11 if(amount >= 0) {
12 balance = amount;
13 } else {
14 System.out.println("金額不能為負數!");
15 }
16 }
17}
繼承(Inheritance)
繼承,顧名思義,就是子類繼承父類的屬性和方法。這就好比你繼承了父母的基因,你可能擁有父親的藍眼睛,母親的卷發。
在Java中,使用extends
關鍵字來實現繼承,子類可以復用父類的代碼,同時還能添加或修改父類的行為,以適應更具體的場景。
繼承不僅提高了代碼的復用性,還支持了“is-a”關系的建模,比如,貓(Cat)是一種動物(Animal),就可以用繼承來表達。
例子:在上面的BankAccount基礎上,我們創建一個更具體的儲蓄賬戶(SavingsAccount),它繼承了BankAccount,并添加了一個計算利息的方法。
1public class SavingsAccount extends BankAccount {
2 private double interestRate; // 儲蓄賬戶特有的屬性:利率
3
4 public SavingsAccount(double initialBalance, double interestRate) {
5 super(); // 調用父類構造器初始化balance
6 setBalance(initialBalance); // 設置初始余額
7 this.interestRate = interestRate; // 設置利率
8 }
9
10 // 添加計算利息的方法
11 public void calculateInterest() {
12 double interest = getBalance() * interestRate;
13 System.out.println("本次獲得利息:" + interest);
14 setBalance(getBalance() + interest); // 更新余額
15 }
16}
多態(Polymorphism)
多態意味著一個接口(可以是抽象類或接口)可以有多種不同的實現方式。
在日常生活中,我們接觸到的“多態”現象比比皆是,比如,按下電視遙控器的“音量+”鍵,不論是哪個品牌的電視,都會執行增大音量的操作,但具體實現方式各不相同。
在Java中,多態主要通過方法重寫(Override)和接口實現來體現。
例子:繼續我們的銀行賬戶例子,假設我們有一個withdraw
(取款)方法,在不同的賬戶類型中可能有不同的實現(如普通賬戶可能直接扣除余額,而信用賬戶可能要考慮透支額度)。
1public abstract class Account {
2 protected double balance;
3
4 public abstract void withdraw(double amount); // 抽象方法,要求子類必須實現
5}
6
7public class CheckingAccount extends Account {
8 @Override
9 public void withdraw(double amount) {
10 if(balance >= amount) {
11 balance -= amount;
12 System.out.println("取款成功,當前余額:" + balance);
13 } else {
14 System.out.println("余額不足!");
15 }
16 }
17}
18
19public class CreditAccount extends Account {
20 private double creditLimit; // 信用額度
21
22 public CreditAccount(double initialBalance, double creditLimit) {
23 super();
24 this.creditLimit = creditLimit;
25 setBalance(initialBalance);
26 }
27
28 @Override
29 public void withdraw(double amount) {
30 if((balance + creditLimit) >= amount) {
31 balance -= amount;
32 System.out.println("信用取款成功,當前余額:" + balance);
33 } else {
34 System.out.println("超過信用額度,取款失敗!");
35 }
36 }
37}
在這個例子中,Account
類定義了一個抽象的withdraw
方法,而CheckingAccount
和CreditAccount
通過各自的方式實現了這個方法,這就是多態的體現。
當我們通過一個Account
類型的引用指向這些子類的實例時,可以根據實際對象的類型調用到相應的實現,無需知道具體的子類類型,大大增強了代碼的靈活性和可擴展性。
封裝、繼承和多態是Java面向對象編程的三大特性,它們共同構建了面向對象設計的堅固基石。
通過封裝保護數據,通過繼承復用代碼,通過多態增強靈活性,這些原則指導我們編寫出更加清晰、靈活和易于維護的Java代碼。