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

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

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"即可。

相关推荐
p***95002 分钟前
Plugin ‘org.springframework.bootspring-boot-maven-plugin‘ not found的解决方法
java·maven
JienDa2 分钟前
JienDa聊PHP:算命平台实战中主流PHP框架的协同架构方略
开发语言·架构·php
h***066512 分钟前
Spring Boot 集成 Kettle
java·spring boot·后端
爱写代码的小朋友21 分钟前
21天学通Python全栈开发实战指南
开发语言·python
苦荞米21 分钟前
异步方法-C#中坑最大最深的功能
开发语言·c#
软件测试曦曦25 分钟前
使用Python接口自动化测试post请求和get请求,获取请求返回值
开发语言·自动化测试·软件测试·python·功能测试·程序人生·职场和发展
旷野说40 分钟前
如何用 Redpanda + 本地事务,实现“发消息 + 写 DB” 的强一致性!
java·数据库·kafka
p***s9142 分钟前
Windows安装Rust环境(详细教程)
开发语言·windows·rust
unclecss1 小时前
从 0 到 1 落地 SSE:Spring Boot 3 实战 Server-Sent Events 推送全链路
java·spring boot·后端·http·sse
e***95641 小时前
springboot-自定义注解
java·spring boot·spring