双面
发布于 2025-06-02 / 54 阅读
0
0

面向对象编程中的封装

在上篇文章,我们学习了面向对象的基本概念,这期我们学习面向对象的三大思想之一的封装

首先、我们看下面的代码

class Person {
    public String name;
    public int age;

    public void introduce() {
        System.out.println("大家好,我叫" + name + ",今年" + age + "岁");
    }
}

public class Demo3 {
    public static void main(String[] args) {
        // 创建一个 Person 对象,并初始化属性
        Person person = new Person();
        person.name = "张三";
        person.age = 18;

        // 调用方法
        person.introduce();
    }
}

运行结果如下:

大家好,我叫张三,今年18岁

进程已结束,退出代码为 0

这样一看,代码有没有啥问题,貌似是正确的,那么,我们改一下,传入的age参数为-1呢,再运行代码

大家好,我叫张三,今年-1岁

进程已结束,退出代码为 0

我们发现,这种不符合常理的数据也成功被赋值了,为了方便,我们叫这种数据为非法数据,这个时候就引用出来封装的第一个作用,对传入的数据进行过滤处理,或者判断是否成功赋值。

那么如何实现呢,首先属性前面是不是有一个public,这个叫访问修饰符,访问修饰符可以决定资源作为引用类型的时候的访问范围,public是公共的,我们需要转换为私有的,private

class Person {
    public String name;
    public int age;

    public void introduce() {
        System.out.println("大家好,我叫" + name + ",今年" + age + "岁");
    }
}

但是,这个时候,我们对资源就不能进行赋值和取值了,(其实这里引出了封装的第二个作用,确定资源的读取和写入权限),所以我们需要写两个行为(get和set)用于控制写入和读取,如果我们的数值不需要写入或者读取,则可以不写这两个方法,这样就有一个只读或者只写的资源

可以看以下代码

class Person {
    private String name;
    private int age;

    public void SetName(String name) {
        this.name = name;
    }

    public String GetName() {
        return this.name;
    }

    public void SetAge(int age) {
        if (age < 0) {
            System.out.println("年龄不合法?1");
        }
    }

    public void introduce() {
        System.out.println("大家好,我叫" + name + ",今年" + age + "岁");
    }
}

public class Demo3 {
    public static void main(String[] args) {
        // 创建一个 Person 对象,并初始化属性
        Person person = new Person();
        person.SetAge(-1);
        person.introduce();
        person.SetAge(20);
        person.SetName("张三");
        System.out.println(person.GetName());

        // 调用方法
        person.introduce();

    }
}

运行结果如下

年龄不合法?1
大家好,我叫null,今年0岁
张三
大家好,我叫张三,今年0岁

进程已结束,退出代码为 0

这里我们对age和name都做了访问限制,然后对age提供了set方法,name提供了get和set方法,这个时候,我们的age就不能直接被读取,只能通过调用类行为使用age的数据,然后,可以看到name的get方法,返回了的是我们set的值,而我们在age的set方法中,写了传入参数的处理,这样就对输入做了过滤处理,可以看到,数据的调用并没有解析数据
总结 :

通过上面的学习和代码演示,我们可以得出封装在面向对象编程中的几个重要作用:

  1. 提高数据的安全性
    使用 private 修饰属性后,外部无法直接访问或修改对象的内部数据,避免了非法数据的赋值问题。例如:年龄不能为负数、姓名不能为空等。

  2. 控制属性的访问权限
    封装允许我们有选择地对外暴露某些属性的读取或写入权限。例如:

    • 只提供 get 方法,表示该属性只能读,不能写(只读属性)。

    • 只提供 set 方法,表示该属性只能写,不能读(虽然这种情况较少)。

    • 同时提供 getset 方法,表示该属性可读可写。

  3. 增强程序的可维护性和扩展性
    通过封装将数据与操作绑定在一起,使得类的使用者不需要关心具体实现细节,只需要按照规定的方法使用即可。如果将来需要修改属性的处理逻辑,只需修改类内部代码,而不会影响到其他使用该类的地方。

  4. 实现数据的过滤与校验
    set 方法中可以加入判断逻辑,对传入的数据进行验证后再决定是否赋值,从而确保数据的合法性和合理性。例如:年龄必须大于0,邮箱格式必须正确等。

  5. 符合面向对象的设计原则——信息隐藏
    类的设计者负责保护类中的数据安全,而使用者只需知道如何调用方法,无需了解内部是如何工作的。这样降低了模块之间的耦合度,提高了程序的健壮性。


评论