博客
关于我
Java 面向对象编程的四个基本原则(封装、继承、多态和抽象),并给出一个简单的例子说明如何在 Java 中应用这些原则?
阅读量:807 次
发布时间:2023-01-27

本文共 4745 字,大约阅读时间需要 15 分钟。

面向对象编程(OOP)是Java编程中的核心概念,它通过对象的划分实现代码的模块化和可维护性。四大基本原则——封装、继承、多态和抽象——是OOP的基石,每个原则都为开发者构建更高效的代码提供了有效的手段。

封装是开发者在对象化编程中首先学习的概念。它指通过将数据和行为捆绑在一起,保护对象的内部实现细节。对 Java 开发者来说,最直观的封装方式是通过字段声明为 private,并通过 setter 和 getter 方法进行访问。例如,银行账户类 BankAccount 中的 balance 字段被声明为 private,外部只能通过 getBalance() 方法获取,这样既保留了控制权,又确保了代码的安全性。

Justice Bank account 类的一个很好的示例是这样的:

public class BankAccount {    private double balance;    public BankAccount(double initialBalance) {        if (initialBalance > 0.0) {            balance = initialBalance;        } else {            throw new IllegalArgumentException("Initial balance must be greater than zero.");        }    }    public double getBalance() {        return balance;    }    public void deposit(double amount) {        if (amount > 0.0) {            balance += amount;        } else {            throw new IllegalArgumentException("Deposit amount must be positive.");        }    }    public void withdraw(double amount) {        if (amount > 0.0 && amount <= balance) {            balance -= amount;        } else {            throw new IllegalArgumentException("Withdrawal amount must be positive and less than or equal to the balance.");        }    }}

通过将 balance 属性私有化并提供公有方法,实现了对账户内部状态的控制。这种封装方法不仅保持代码的安全性,还允许我们在必要时添加各种校验逻辑。

继承则是在OOP中进一步强化代码复用性的一个重要概念。它允许一个子类继承父类的属性和方法,从而避免重复编写代码。比如,SavingsAccount 类可以继承 BankAccount 的大部分功能,并添加互利计算的方法。这种继承方式使得代码结构层次分明,易于扩展和维护。

对于继承的示例,我们可以创建一个扩展 BankAccount 的 SavingsAccount 类:

public class SavingsAccount extends BankAccount {    private double interestRate;    public SavingsAccount(double initialBalance, double interestRate) {        super(initialBalance);        this.interestRate = interestRate;    }    public void addInterest() {        double interest = getBalance() * interestRate;        deposit(interest);    }}

通过这种继承方式,我们不仅复用了父类的方法,还确保了子类的唯一性和功能特异性。

多态的概念与继承结合使用时特别有用。它允许一个对象以多种形式表现出不同的行为。例如,在 BankAccount 类中定义一个 abstract 方法 calculateInterest(),然后由具体的子类如 SavingsAccount 实现。这使得我们能够在不关心具体实现的情况下,统一处理所有类型的账户。

对于多态的实现,可以考虑如下代码:

public abstract class BankAccount {    private double balance;    public BankAccount(double initialBalance) {        if (initialBalance > 0.0) {            balance = initialBalance;        } else {            throw new IllegalArgumentException("Initial balance must be greater than zero.");        }    }    public double getBalance() {        return balance;    }    public void deposit(double amount) {        if (amount > 0.0) {            balance += amount;        } else {            throw new IllegalArgumentException("Deposit amount must be positive.");        }    }    public void withdraw(double amount) {        if (amount > 0.0 && amount <= balance) {            balance -= amount;        } else {            throw new IllegalArgumentException("Withdrawal amount must be positive and less than or equal to the balance.");        }    }    public abstract double calculateInterest();}

然后,SavingsAccount 类可以实现这个方法:

public class SavingsAccount extends BankAccount {    private double interestRate;    public SavingsAccount(double initialBalance, double interestRate) {        super(initialBalance);        this.interestRate = interestRate;    }    @Override    public double calculateInterest() {        return getBalance() * interestRate;    }}

这样,在同一个方法中,可以支持多种类型的账户,这就是多态的力量所在。

抽象类或接口是实现多态和抽象概念的重要手段。通过定义一组通用行为,我们可以让不同类型的对象遵循相同的接口。例如,Account 接口定义了基本的存取行为,而 BankAccount 和 SavingsAccount 类都实现这个接口。这样一来,我们可以在不关心具体实现的情况下,写出通用的代码。

一个最好的方法是创建一个Account 接口:

public interface Account {    void deposit(double amount);    void withdraw(double amount);    double getBalance();}

然后,具体的 BankAccount 类实现它:

public class BankAccount implements Account {    private double balance;    public BankAccount(double initialBalance) {        if (initialBalance > 0.0) {            balance = initialBalance;        } else {            throw new IllegalArgumentException("Initial balance must be greater than zero.");        }    }    public void deposit(double amount) {        if (amount > 0.0) {            balance += amount;        } else {            throw new IllegalArgumentException("Deposit amount must be positive.");        }    }    public void withdraw(double amount) {        if (amount > 0.0 && amount <= balance) {            balance -= amount;        } else {            throw new IllegalArgumentException("Withdrawal amount must be positive and less than or equal to the balance.");        }    }    public double getBalance() {        return balance;    }}

通过这种方式,所有账户类型都遵循相同的接口,从而可以在一个通用的方法中处理它们的行为。

Developers 的最佳实践可以总结为:

  • 封装:尽量将字段设为 private,并通过 getter 和 setter 方法提供必要的访问点,并在 setter 中添加必要的验证逻辑。
  • 继承:仅用于共享行为和状态的类之间,避免过度继承导致代码混乱。
  • 多态:利用抽象类或接口定义通用行为,并在子类中定制实现。
  • 抽象:使用抽象类或接口来定义通用行为规范,确保代码的扩展性。
  • 在实际开发中,需注意避免过度封装、过度继承,避免接口过于庞大,和避免为了抽象而抽象。

    转载地址:http://tfryk.baihongyu.com/

    你可能感兴趣的文章
    mppt算法详解-ChatGPT4o作答
    查看>>
    mpvue的使用(一)必要的开发环境
    查看>>
    MQ 重复消费如何解决?
    查看>>
    mqtt broker服务端
    查看>>
    MQTT 保留消息
    查看>>
    MQTT 持久会话与 Clean Session 详解
    查看>>
    MQTT介绍及与其他协议的比较
    查看>>
    MQTT工作笔记0007---剩余长度
    查看>>
    MQTT工作笔记0008---服务质量
    查看>>
    MQTT工作笔记0009---订阅主题和订阅确认
    查看>>
    Mqtt搭建代理服务器进行通信-浅析
    查看>>
    MS COCO数据集介绍
    查看>>
    MS Edge浏览器“STATUS_INVALID_IMAGE_HASH“兼容性问题
    查看>>
    ms sql server 2008 sp2更新异常
    查看>>
    MS SQL查询库、表、列数据结构信息汇总
    查看>>
    MS UC 2013-0-Prepare Tool
    查看>>
    MSBuild 教程(2)
    查看>>
    msbuild发布web应用程序
    查看>>
    MSB与LSB
    查看>>
    MSCRM调用外部JS文件
    查看>>