在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代码。