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

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

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

相关推荐
长安第一美人1 天前
C 语言可变参数(...)实战:从 logger_print 到通用日志函数
c语言·开发语言·嵌入式硬件·日志·工业应用开发
Larry_Yanan1 天前
Qt多进程(一)进程间通信概括
开发语言·c++·qt·学习
superman超哥1 天前
仓颉语言中基本数据类型的深度剖析与工程实践
c语言·开发语言·python·算法·仓颉
不爱吃糖的程序媛1 天前
Ascend C开发工具包(asc-devkit)技术解读
c语言·开发语言
bu_shuo1 天前
MATLAB奔溃记录
开发语言·matlab
韩立学长1 天前
【开题答辩实录分享】以《自助游网站的设计与实现》为例进行选题答辩实录分享
java·mysql·spring
ss2731 天前
线程池:任务队列、工作线程与生命周期管理
java·后端
不像程序员的程序媛1 天前
Spring的cacheEvict
java·后端·spring
SAP小崔说事儿1 天前
在数据库中将字符串拆分成表单(SQL和HANA版本)
java·数据库·sql·sap·hana·字符串拆分·无锡sap
凌云若寒1 天前
半导体代加工企业标签模板痛点的全景式解决方案
java