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

    你可能感兴趣的文章
    Elasticsearch下载安装
    查看>>
    Elasticsearch入门教程(Elasticsearch7,linux)
    查看>>
    elasticsearch的helpers.bulk和es_client.bulk的用法
    查看>>
    ElasticSearch设置字段的keyword属性
    查看>>
    Elasticsearch设置账号密码
    查看>>
    elasticsearch配置文件里的一些坑 [Failed to load settings from [elasticsearch.yml]]
    查看>>
    Elasticsearch面试题
    查看>>
    element ui 时间日期选择器 el-date-picker 报错 Prop being mutated “placement“
    查看>>
    Hibernate二级缓存配置
    查看>>
    element 如何使用自定义icon图标
    查看>>
    element-plus修改主题颜色
    查看>>
    element-plus的el-date-picker日期范围选择控件,根据开始日期限定结束日期的可选范围为开始日期到开始日期+30天
    查看>>
    18 个一线工作中常用 Shell 脚本【实用版】
    查看>>
    element-ui:el-input输入数字-整数和小数
    查看>>
    ElementUI-el-progress改变进度条颜色跟文字样式
    查看>>
    element事件(change,click)不触发
    查看>>
    ELK原理与介绍(转)
    查看>>
    ELK学习笔记(三)单台服务器多节点部署
    查看>>
    ELK应用日志收集实战
    查看>>
    elTable火狐浏览器换行
    查看>>