面向对象设计-封装

封装,就是将类的某些信息隐藏在类内部,不允许外部程序直接访问,而是通过该类提供的方法来实现对隐藏信息的操作和访问。

封装的步骤:

  • 修改属性的可见性(使用 private 修饰)
  • 创建 getter/setter 方法,用于属性的读写,一般此方法是用 public 修饰。
  • 必要时可以在 getter/setter 方法添加逻辑控制语句,保证属性的合法性。

前面我们已经给大家介绍了类和对象,当时我们没有介绍对象的特征封装。那到底什么是封装呢?它的好处又是什么呢?接下来让我一一为你揭秘。

我们都知道每一个人都有自己的小秘密,不想被别人所熟知。同样在 Java 世界中的对象也有自己的隐私,对象的隐私就是对象内部的实现细节。那如何保护这些隐私呢,这就需要我们的封装来实现了 😊。

  1. 封装的概念。 封装就是将类的某些信息隐藏在类内部,不允许外部程序直接访问,而是通过该类提供的方法来实现对隐藏信息的操作和访问。

  2. 封装的目的是简化编程和增强安全性。

    • 简化编程是指,封装可以让使用者不必了解具体类的内部实现细节,而只是要通过提供给外部访问的方法来访问类中的属性和方法。例如 Java API 中的 Arrays.sort()方法,该方法可以用于给数组进行排序操作,开发者只需要将待排序的数组名放到 Arrays.sort()方法的参数中,该方法就会自动的将数组排好序。可见,开发者根本不需要了解 Arrays.sort()方法的底层逻辑,只需要简单的将数组名传递给方法即可实现排序。
    • 增强安全性是指,封装可以使某个属性只能被当前类使用,从而避免被其他类或对象进行误操作。例如在 Student.java 的程序中,StudentstuAge 属性是 public 的形式体现的,但这样做实际存在着安全隐患:TestStudent 类(或在访问修饰符可见范围内的其他类)完全可以随意的对 stuAge 进行修改,如以下程序。
arduino 复制代码
/**
 * 定义一个学生类
 * @author lanqiao
 */
public class Student {
    public String stuName;     // 学生姓名
    public int stuAge;      // 学生年龄
    ...
}
ini 复制代码
/**
 * 定义一个学生测试类
 * @author lanqiao
 */
public class TestStudent {
    public static void main(String[] args) {
        Student xiaolan = new Student();
        xiaolan.stuName = "小蓝";
        xiaolan.stuAge = -10;
        ...
    }
}

如上,给 stuAge 赋了一个不符合逻辑的值,但语法是却正确的。因此这种做法,实际会给程序造成一定程度上的安全问题。那么此时我们就可以使用封装Student.java 内部的信息不能随便被外部访问,要想访问可以通过供外部访问的方法去访问。

封装好处:a. 只能通过规定的方法访问数据; b.隐藏类的实例细节,方便修改和实现。

  1. 封装的实现步骤。

根据上图中的步骤,我们来修改 Student.java 程序中的代码,然后在 TestStudent 类进行测试:

  • 使用 private 修饰 Student.java 文件中的成员变量,给每个成员变量添加一个 getter/setter 方法并且给变量添加合适的逻辑控制语句:
typescript 复制代码
/**
 * 定义一个学生类
 * @author lanqiao
 */
public class Student {
    private String stuName;  //学生姓名
    private int stuAge;      //学生年龄

    // 给属性提供 getter/setter 方法
    // 获取stuName的值
    public String getStuName(){
        return stuName;
    }

    // 给 stuName 赋值
    public void setStuName(String name){
        stuName = name;
    }

    // 获取 stuAge 的值
    public int getStuAge(){
        return stuAge;
    }

    // 给 stuAge 的赋一个合法的值
    public void setStuAge(int age){
        //如果年龄在合理范围内,则正常赋值
        if( age >0 && age <120){
            stuAge = age;
        }else{ //如果对年龄的赋值不合理,则设置为默认值0
            stuAge = 0 ;
        }
    }
}
  • 修改 TestStudent.java 文件中的代码:
arduino 复制代码
/**
 * 定义一个学生测试类
 * @author lanqiao
 */
public class TestStudent {
    public static void main(String[] args) {
        Student xiaolan = new Student();
        /* 如果将stuAge赋值负数,setStuAge()就会将stuAge设置为默认值0,防止出现安全问题。
        xiaolan.setStuAge(-10); */
        xiaolan.setStuAge(22); // 给年龄赋值
        xiaolan.setStuName("小蓝");
        int age = xiaolan.getStuAge() ;
        String name = xiaolan.getStuName();

        System.out.println("姓名:" + name + "\t年龄:" + age);
    }
}
  • 编译运行程序,最终结果如下图所示:

    javac TestStudent.java
    java TestStudent

⭐ 上面我们已经使用面向对象的特征封装改造好了程序,接下来我们一起来分析总结一下:

  • 使用 private 修饰符修饰的成员信息,外部不能直接访问(包括成员变量和成员方法)。

  • 使用 private 可以保证安全,但是如果其他类想需要这些信息,那该怎么办呢?有没有一种办法,既能让其他类可以访问类中使用private 修饰的成员信息,又能保证获取到的信息合法并安全呢?有,那就是给该属性提供两个 public 修饰的、保证属性安全的访问方法(setter 方法和 getter 方法),即:

    a. 用 private 禁止其他类直接访问属性;

    b. 给 private 修饰的属性新增两个 public 修饰的 settergetter 方法,供其他类安全的访问。

  • setter 方法用于给属性赋值,而 getter 访问用于获取属性的值。正常情况下,setter 方法的名字通常是 set+属性名getter 方法的名字通常是 get+属性名,记住方法的命名规则------首字母小写,如果方法名由多个单词组成,除了第一个单词,其它每个单词的首字母都要大写。

以上就是对象的第一个特征:封装,不难吧 😊。

相关推荐
Estar.Lee3 小时前
查手机号归属地免费API接口教程
android·网络·后端·网络协议·tcp/ip·oneapi
2401_857610034 小时前
SpringBoot社团管理:安全与维护
spring boot·后端·安全
凌冰_5 小时前
IDEA2023 SpringBoot整合MyBatis(三)
spring boot·后端·mybatis
码农飞飞5 小时前
深入理解Rust的模式匹配
开发语言·后端·rust·模式匹配·解构·结构体和枚举
一个小坑货5 小时前
Rust 的简介
开发语言·后端·rust
monkey_meng5 小时前
【遵守孤儿规则的External trait pattern】
开发语言·后端·rust
Estar.Lee6 小时前
时间操作[计算时间差]免费API接口教程
android·网络·后端·网络协议·tcp/ip
新知图书6 小时前
Rust编程与项目实战-模块std::thread(之一)
开发语言·后端·rust
盛夏绽放7 小时前
Node.js 和 Socket.IO 实现实时通信
前端·后端·websocket·node.js
Ares-Wang7 小时前
Asp.net Core Hosted Service(托管服务) Timer (定时任务)
后端·asp.net