面向对象(上)-封装性的引入

面向对象(上)-封装性的引入

4.7 面相对象特征之一:封装和隐藏

  • 为什么需要封装?封装的作用和含义?

    我要用洗衣机,只需要按一下开关和洗涤模式即可,不需要了解洗衣机的内部构造和洗衣原理。

  • 我们的程序设计追求"高内聚,低耦合"

    高内聚:类的内部数据操作细节自己完成,不允许外部干涉;

    低耦合:仅对外暴露少量的方法用于使用。

  • 隐藏对象内部的复杂性,只对外公开简单的接口。便于外接调用,从而提高系统的可扩展性、可维护性。通俗的说:把该隐藏的隐藏起来,该暴露的暴露出来。

问题的引入

当我们创建一个类的对象以后,我们可以通过"对象.属性"的方式,对对象的属性进行赋值。

这里复制操作是受属性的数据类型和存储范围限制,除此之外没有其他制约条件。

但是实际问题中,我们往往需要给属性复制假如额外的限制,就不能只做属性的申明,需要通过方法添加体现。(eg:setLegs、getLegs)

举例:假设我们有一个类描述"狗",其中有个属性legs表示狗腿的数量。如果只要int legs,那么用户有可能传入负数,显然狗腿数量不可能为负数,需要使用方法对传入的数进行限制,且限制用户直接调用"对象.属性"进行赋值。

java 复制代码
    public static void main(String[] args){
        Dog dog = new Dog();
        // dog.legs = -6;   // 编译报错,'legs' has private access in 'com.example.xu_ni_ping.Dog'
        dog.setLegs(-6);
        dog.getLegs();   // 输出0
        dog.setLegs(4);
        dog.getLegs();   // 输出4
    }
java 复制代码
public class Dog {
    private int legs;   // 设置为私有,防止用户调用

    // 设置腿的数量
    public void setLegs(int l) {
        if (l >= 0) {
            legs = l;
        } else {
            legs = 0;  // 如果传入的值为负数,就设置为0;
            // 或者抛出异常;
        }
    }

    // 获取腿的数量
    public int getLegs() {
        System.out.println(legs);
        return legs;
    }
}

封装性的体现

我们需要避免用户在使用"对象.属性"的方式对属性进行赋值,所以我们需要将属性私有化(private),并提供setLegs和getLegs方法。这就体现出了属性以及方法的封装性。

拓展:封装性的体现包含,属性私有化,提供get和set方法;不对外暴露的私有化方法;单例模式等。

权限修饰符

封装性的体现,需要权限修饰符来配合:

java规定的4种权限,从小到大排序:private、default(缺省时默认)、protected、public

修饰符 类内部 同一个包 不同包的子类 同一个工程
private yes
default yes yes
protected yes yes yes
public yes yes yes yes

4种权限可以用来修饰类以及类的内部结构(属性、方法、构造器、内部类)

  • 对于类:使用default、public;
  • 对于类的内部结构(属性、方法、构造器、内部类):private、default、protected、public都行;

封装性举例

例子:创建程序,在其中定义两个类:Person和PersonTest类。定义如下:用setAge()设置人的合法年龄(0-130),用getAge()返回人的年龄。在PersonTest类种的实例化Person类的对象b,调用setAge()和getAge()方法,体现Java封装性

java 复制代码
    public static void main(String[] args){
        Person person = new Person();
        // person.age = 18;  // 'age' has private access in 'com.example.xu_ni_ping.Person'
        person.setAge(18);
        System.out.println(person.getAge());  // 输出18
        person.setAge(-18);
        System.out.println(person.getAge());    // 运行报错:java.lang.RuntimeException: 传入的年龄非法!at com.example.xu_ni_ping.Person.setAge(Person.java:15)
    }
java 复制代码
public class Person {

    private int age;

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        if (age >= 0 && age <= 130) {
            this.age = age;
        } else {
            throw new RuntimeException("传入的年龄非法!");
        }
    }
}

快速生成set、get方法:

在类的空白处点击鼠标右键。

选择"Generate"。

选择"Getter and Setter"。

选择需要生成getter和setter方法的字段,点击"OK"即可。

相关推荐
夏幻灵2 小时前
JavaScript this 面试:五种绑定规则、优先级与常见面试陷阱
开发语言·javascript·面试
程序猿编码2 小时前
榨干 RTX5090 算力!Qwen3 专用单卡推理引擎,手写C++/CUDA 算子实现 MTP 推测解码
开发语言·c++·大模型推理·qwen3·多模态推理
bkspiderx4 小时前
Qt 插件机制:动态扩展应用功能的核心框架
开发语言·qt·元数据·qt 插件·qpluginloader
代码什么用4 小时前
Spring基础使用
java·后端·spring
程序员老陆4 小时前
深入理解 C++ thread_local:线程私有存储的正确打开方式
开发语言·c++·程序设计
沐晓时光4 小时前
C语言入门,深入理解指针(3)
c语言·开发语言
Su米苏4 小时前
Spring AI 中MCP 与普通 @Tool的区别
java·人工智能·spring
码云数智-园园4 小时前
unique_ptr 还是 shared_ptr?C++ 智能指针选型与内存泄漏实战分析
java·开发语言
老板一杯拿铁4 小时前
Java 异常体系详解:从字节码原理到最佳实践
java
蜗牛互联网5 小时前
Java 17 HttpClient调用文件转写API的超时与失败回退
java·人工智能·后端