首页 > 编程语言 >Java 面向对象编程的四个基本原则(封装、继承、多态和抽象),并给出一个简单的例子说明如何在 Java 中应用这些原则?

Java 面向对象编程的四个基本原则(封装、继承、多态和抽象),并给出一个简单的例子说明如何在 Java 中应用这些原则?

时间:2024-09-02 21:53:58浏览次数:10  
标签:BankAccount Java double void 多态 amount 面向对象编程 balance public

面向对象编程(OOP)是一种编程范式,它使用“对象”来设计软件。在 Java 中,面向对象编程的四个基本原则是封装、继承、多态和抽象。每个原则都有其特定的目标,帮助开发者构建更加模块化、可维护和可扩展的代码。

封装

封装是指将数据(属性)和行为(方法)捆绑在一起,并隐藏对象的具体实现细节。封装的好处是可以保护对象内部状态的完整性,防止外部代码随意修改对象的状态,从而提高了代码的安全性和可靠性。

代码示例

假设我们有一个 BankAccount 类,我们需要保护账户余额不被外部直接修改。

1public class BankAccount {
2    private double balance;
3
4    public BankAccount(double initialBalance) {
5        if (initialBalance > 0.0) {
6            balance = initialBalance;
7        } else {
8            throw new IllegalArgumentException("Initial balance must be greater than zero.");
9        }
10    }
11
12    public double getBalance() {
13        return balance;
14    }
15
16    public void deposit(double amount) {
17        if (amount > 0.0) {
18            balance += amount;
19        } else {
20            throw new IllegalArgumentException("Deposit amount must be positive.");
21        }
22    }
23
24    public void withdraw(double amount) {
25        if (amount > 0.0 && amount <= balance) {
26            balance -= amount;
27        } else {
28            throw new IllegalArgumentException("Withdrawal amount must be positive and less than or equal to the balance.");
29        }
30    }
31}

这里我们通过将 balance 属性声明为 private 来隐藏其内部实现,并提供了公共的方法(getBalance()deposit()withdraw())来访问和修改余额。

继承

继承是指一个类(子类)可以继承另一个类(父类)的属性和方法。继承使得子类可以在复用父类功能的基础上添加或覆盖特定的行为,从而实现代码的重用。

代码示例

继续使用 BankAccount 类,我们可以创建一个 SavingsAccount 子类来继承 BankAccount 的功能,并添加一些特定的功能,比如利息计算。

1public class SavingsAccount extends BankAccount {
2    private double interestRate;
3
4    public SavingsAccount(double initialBalance, double interestRate) {
5        super(initialBalance);
6        this.interestRate = interestRate;
7    }
8
9    public void addInterest() {
10        double interest = getBalance() * interestRate;
11        deposit(interest);
12    }
13}

在这里,SavingsAccount 继承了 BankAccount 的所有属性和方法,并添加了一个 addInterest() 方法来计算并添加利息。

多态

多态是指一个类的对象可以被当作其父类或其他接口类型来使用。多态允许我们编写更通用的代码,可以处理多种类型的对象。

代码示例

我们可以在 BankAccount 类中添加一个 calculateInterest() 方法,并让 SavingsAccount 类重写这个方法。

1public abstract class BankAccount {
2    private double balance;
3
4    public BankAccount(double initialBalance) {
5        if (initialBalance > 0.0) {
6            balance = initialBalance;
7        } else {
8            throw new IllegalArgumentException("Initial balance must be greater than zero.");
9        }
10    }
11
12    public double getBalance() {
13        return balance;
14    }
15
16    public void deposit(double amount) {
17        if (amount > 0.0) {
18            balance += amount;
19        } else {
20            throw new IllegalArgumentException("Deposit amount must be positive.");
21        }
22    }
23
24    public void withdraw(double amount) {
25        if (amount > 0.0 && amount <= balance) {
26            balance -= amount;
27        } else {
28            throw new IllegalArgumentException("Withdrawal amount must be positive and less than or equal to the balance.");
29        }
30    }
31
32    public abstract double calculateInterest();
33}
34
35public class SavingsAccount extends BankAccount {
36    private double interestRate;
37
38    public SavingsAccount(double initialBalance, double interestRate) {
39        super(initialBalance);
40        this.interestRate = interestRate;
41    }
42
43    @Override
44    public double calculateInterest() {
45        return getBalance() * interestRate;
46    }
47}

现在,我们可以在父类中定义一个抽象方法 calculateInterest(),然后在子类中实现它。这样,我们就可以编写一个通用的方法来处理不同的账户类型。

1public void printInterest(BankAccount account) {
2    System.out.println("Interest: " + account.calculateInterest());
3}
4
5public static void main(String[] args) {
6    BankAccount savings = new SavingsAccount(1000, 0.05);
7    printInterest(savings); // 输出 "Interest: 50.0"
8}

抽象

抽象是指通过抽象类或接口来定义一组通用的行为,而不关心具体实现细节。抽象类或接口可以被其他类继承或实现,从而达到代码复用的目的。

代码示例

我们可以创建一个 Account 接口来定义所有账户都应该有的基本行为,然后让 BankAccountSavingsAccount 实现这个接口。

1public interface Account {
2    void deposit(double amount);
3    void withdraw(double amount);
4    double getBalance();
5}
6
7public class BankAccount implements Account {
8    private double balance;
9
10    public BankAccount(double initialBalance) {
11        if (initialBalance > 0.0) {
12            balance = initialBalance;
13        } else {
14            throw new IllegalArgumentException("Initial balance must be greater than zero.");
15        }
16    }
17
18    @Override
19    public void deposit(double amount) {
20        if (amount > 0.0) {
21            balance += amount;
22        } else {
23            throw new IllegalArgumentException("Deposit amount must be positive.");
24        }
25    }
26
27    @Override
28    public void withdraw(double amount) {
29        if (amount > 0.0 && amount <= balance) {
30            balance -= amount;
31        } else {
32            throw new IllegalArgumentException("Withdrawal amount must be positive and less than or equal to the balance.");
33        }
34    }
35
36    @Override
37    public double getBalance() {
38        return balance;
39    }
40}
41
42public class SavingsAccount extends BankAccount implements Account {
43    private double interestRate;
44
45    public SavingsAccount(double initialBalance, double interestRate) {
46        super(initialBalance);
47        this.interestRate = interestRate;
48    }
49
50    public void addInterest() {
51        double interest = getBalance() * interestRate;
52        deposit(interest);
53    }
54
55    @Override
56    public double calculateInterest() {
57        return getBalance() * interestRate;
58    }
59}

通过这种方式,我们可以确保所有的账户类型都遵循相同的接口,从而更容易地交换和组合它们。

合理化的使用建议

  1. 封装

    • 尽可能将类的属性设为 private,并通过公共方法暴露必要的访问途径。
    • 使用 getter 和 setter 方法来增加数据访问的安全性,比如添加校验逻辑。
  2. 继承

    • 继承应仅用于共享行为和状态的类之间。
    • 避免过度继承,因为这可能会导致代码难以维护。
  3. 多态

    • 利用多态可以让代码更具通用性和灵活性。
    • 通过抽象类或接口定义通用行为,并在具体实现中进行定制。
  4. 抽象

    • 使用抽象类或接口来定义通用的行为和规范。
    • 抽象类可以提供部分实现,而接口则只定义方法签名。

实际开发过程中的注意点:

  • 过度封装
    过度封装可能会导致代码变得过于复杂。适当暴露一些属性,如通过 final 修饰符,可以让代码更简洁。

  • 过度继承
    过度继承可能会导致类层次结构过于复杂,从而影响代码的可读性和可维护性。

  • 接口污染
    在设计接口时,要确保接口的功能单一,避免接口过于庞大,导致实现类需要实现大量无关的方法。

  • 滥用抽象
    抽象类和接口应该用来定义行为,而不是具体实现。避免为了抽象而抽象,导致设计复杂度上升。

通过合理地应用面向对象编程的原则,我们可以编写出更加健壮、易于维护和扩展的代码。在实际项目中,我们应该根据具体的需求灵活运用这些原则,以达到最佳的设计效果。

标签:BankAccount,Java,double,void,多态,amount,面向对象编程,balance,public
From: https://blog.csdn.net/liangzai215/article/details/141831481

相关文章

  • Java 面试题:事务隔离级别以及并行事务会出现什么问题&&怎么解决脏读、不可重复读和幻
    文章目录四种事务隔离级别MySQL中设置事务隔离级别四种事务隔离级别在并行事务中可能会遇到的问题脏读、不可重复读和幻读三者区别事务的隔离级别是怎么解决这三个问题的?ReadView是什么ReadView包含的信息ReadView在MVCC中的工作原理工作流程总结事务的隔......
  • 探索Groovy的Elvis操作符及其在Java中的替代方案
    在编程的世界里,我们经常需要处理变量的默认值问题,尤其是在变量可能为null的情况下。Groovy语言提供了一种优雅的方式来处理这种情况,那就是Elvis操作符。本文将探讨Elvis操作符的用法,并展示如何在Java中实现类似的功能。Elvis操作符简介Elvis操作符(?:)是Groovy语言中的一种......
  • 解耦利器 - Java中的SPI机制
    为什么需要SPI机制SPI和API的区别是什么SPI是一种跟API相对应的反向设计思想:API由实现方确定标准规范和功能,调用方无权做任何干预;而SPI是由调用方确定标准规范,也就是接口,然后调用方依赖此接口,第三方实现此接口,这样做就可以方便的进行扩展,类似于插件机制,这是SPI出现的需求背景。......
  • 解耦利器 - Java中的SPI机制
    为什么需要SPI机制SPI和API的区别是什么SPI是一种跟API相对应的反向设计思想:API由实现方确定标准规范和功能,调用方无权做任何干预;而SPI是由调用方确定标准规范,也就是接口,然后调用方依赖此接口,第三方实现此接口,这样做就可以方便的进行扩展,类似于插件机制,这是SPI出现的需求背景。......
  • JAVA 内部类与Lambda
    JAVA内部类与Lambda目录JAVA内部类与Lambda1内部类1.1内部类基础1.2私有成员内部类1.3静态内部类1.4局部内部类1.5匿名内部类2Lambda表达式2.1初识Lambda2.1.1无参无返回值抽象方法2.1.2Lambda有参无返回值抽象方法2.1.3Lambda无参有返回值抽象方法2.1.4有参有......
  • Java API:MATH
    JavaAPI:MATH目录JavaAPI:MATH1MATH2示例1MATHMath包含执行基本数字运算的方法;Math类提供的所有方法都是类方法;Math类方法变量和类型方法描述staticintabs(inta)返回int值的绝对值。staticdoubleceil(doublea)返回大于或等于参数且等于数学......
  • Java API:System
    JavaAPI:System目录JavaAPI:System1System2示例代码1SystemSystem类包含几个有用的类字段和方法。它无法实例化。System类提供的设施包括标准输入,标准输出和错误输出流;访问外部定义的属性和环境变量;加载文件和库的方法;以及用于快速复制阵列的一部分的实用方法。......
  • Java API:Object and Objects
    JavaAPI:ObjectandObjects目录JavaAPI:ObjectandObjects1Object1.1常用方法1.1Object类的toString方法1.1.1示例1.2equals1.2.1示例1.2.2面试题2Objects2.1示例1Object类Object是类层次结构的根。每个class都有Object作为超类。所有对象(包括数组)都实现此类的方......
  • Java API:BigDecimal
    JavaAPI:BigDecimal目录JavaAPI:BigDecimal1BigDecimal2示例1BigDecimalBigDecimal类使用户完全控制舍入行为。如果未指定舍入模式,并且无法表示确切的结果,则抛出异常;否则,可以通过向操作提供适当的MathContext对象来进行计算,以选择精度和舍入模式。在这两种情况下,都......
  • 浙江省会计人员继续教育刷课脚本-JavaScript编写
    脚本学习网站:浙江省会计人员继续教育:https://jxjy.czt.zj.gov.cn/front/jxjy.html脚本地址:浙江省会计人员继续教育-刷课脚本:https://greasyfork.org/zh-CN/scripts/506412-浙江省会计人员继续教育-刷课脚本教程1.插件安装(以MicrosoftEdge浏览器为例)打开最中间那个蓝色......