美文网首页Java java学习
面向对象三大特性(一):封装

面向对象三大特性(一):封装

作者: 许宏川 | 来源:发表于2015-07-22 02:07 被阅读219次

面向对象有三大特性:封装、继承和多态。注意,是面向对象的三大特性而不是Java的三大特性,Java只是面向对象语言的一种。这篇文章说说其中的一个特性:封装。

面向对象的类是把程序逻辑里需要的属性和方法抽象出来放到合适的类里。而我们在把类的成员(属性和方法)打包成类后,我们还要对类和类的成员的信息进行适当的隐藏和对访问权限进行限制。这就是封装。

封装分两个层面,一是类本身的封装和类的成员的封装。
实现封装的语法有以下两个

  • 访问控制符
  • getter和setter

访问控制符##

Java有四个访问修饰符,按访问范围从小到大排序分别是<code>private</code>、<code>default</code>、<code>protected</code>、<code>public</code>。其中default并不是有这个关键字,而是没有写访问修饰符即缺省的意思。
这些访问修饰符可以修饰类也可以修饰类的成员。
修饰类时控制的是这个类在什么范围内允许被实例化。类只能被public和default修饰,不能被private和protected修饰。如果用public修饰则没有限制在哪都可以被实例化,如果用defalut修饰则在同一个包下才能被实例化。实际使用中我们会把大部分类都用public修饰。什么情况用defalut修饰类呢,这个等学到内部类时再就知道了。

修饰类的成员时控制的是这个成员在什么范围内允许被访问。四个访问修饰符都可以用于修饰类的成员,其权限如下表所示。


用public修饰的成员在整个项目里都能访问。而用protected修饰的成员只有子类可以访问(这个等学习继承时再详细说),default是同一个包内可以访问,再次解释下没有default这个关键字,就是什么访问修饰符都不写的意思。而private范围范围最小,只有本类里可以访问。

来看示例。例如我们有一个操作系统类OS,有以下几个属性。

String name; //系统名称
String language; //系统语言
int timeZone; //时区

如果我们把这些属性都用public,那是不是到处都可以通过对象名和小圆点来获取或者修改值?那如果像下面这样瞎改是不是就不安全了?

OS myOS = new OS();
myOS.name = "塞牙班";
myOS.language = "@#¥%";
myOS.timeZone = 25;

所以我们需要对需要对这些属性进行权限回收。把访问修饰符改为private私有的。这下好了,因为别的地方不能访问这些属性了,但这下也糟了,也是因为别的地方不能访问这些属性了。所以这时就需要<code>getter()</code>和<code>setter()</code>出场了。

getter()和setter()##

我们对属性的保护完整的做法除了用private私有化外,还需要对外提供公有化的访问方法。也就是获取值得方法getter()和设置值的方法setter()。如果一个属性完全不想被其它类访问只是类内部私用那么就不要提供getter()和setter()。如果只允许访问值而不允许被修改那么只提供getter()而不提供setter(),如果允许被修改值那么可以提供setter()方法,设置成什么值通过参数传递给setter(),然后setter()可以通过传进来的参数进行判断这个值是否合法。例如地球之友24个时区,如果传进来一个25就不对了,修改失败。
我把OS的代码写成下面这样:

public class OS {

    private String name; //系统名称
    private String language; //系统语言
    private int timeZone; //时区

    public String getName() {
        return name;
    }

    public String getLanguage() {
        return language;
    }

    public void setLanguage(String language) { //简化,假设这个世界只有这四种文字
        if (language == "中文(简体)" || language == "中文(繁體)" || language == "English" || language == "français") {
            this.language = language;
        }
    }

    public int getTimeZone() {
        return timeZone;
    }

    public void setTimeZone(int timeZone) { //地球只有24个时区
        if (timeZone >= 0 && timeZone <= 24) {
            this.timeZone = timeZone;
        }
    }

    //无参数构造方法
    public OS() {
        this.name = "dos";
        this.language = "English";
        this.timeZone = 17;
    }

}

tips:可以通过快捷键alt + insert快捷键添加getter()和setter(),在弹出来的对话框用ctrl键多选要添加哪些属性的getter()和setter()。


再写个测试类Test

public class Test {

    public static void main(String[] args) {
        OS myOS = new OS();
        System.out.println(myOS.getName());
        myOS.setLanguage("中文(简体)");
        System.out.println(myOS.getLanguage());
        myOS.setTimeZone(8);
        System.out.println(myOS.getTimeZone());
    }

}

运行结果:

<pre>
dos
English
8
</pre>

以上是对属性进行的封装,那方法呢?
我创建一个PC类,代码如下。

public class PC {
    
    private String processor; //处理器
    private int memory; //内存
    private String videoCard; //显卡
    private int hardDrive; //硬盘
    private int display; //屏幕
    private com.xuhongchuan.os.OS OS; //操作系统

    public String getProcessor() {
        return processor;
    }

    public int getMemory() {
        return memory;
    }

    public String getVideoCard() {
        return videoCard;
    }

    public int getHardDrive() {
        return hardDrive;
    }

    public int getDisplay() {
        return display;
    }

    public OS getOS() {
        return OS;
    }

    public void setOS(OS os) {
        this.OS = os;
    }

    /**
     * 无参构造方法
     */
    public PC() {
        System.out.println("一台新的电脑诞生了。");
    }

    public void startup() {
        System.out.println("开机");
        System.out.println("硬件自检");
        System.out.println("引导操作系统启动");
        OS.startup();
    }

    public void shutDown() {
        System.out.println("关机");
    }

}

PC有处理器、内存、显卡、硬盘、屏幕、操作系统这些属性,出于安全考虑都要设置成private的。但是用户是可以知道这些属性的,所以都添加了getter()。但是一台电脑能不能自行DIY修改配置不一定,所以除了可以setOS()装系统外没有添加其它属性的setter()。那有的电脑就是可以自行升级配置setter()写在哪呢?这个等学继承时再来处理。

然后我们再给OS类添加以下方法:

    //开机启动系统
    public void startup() {
        System.out.println(this.name + "系统启动了");
    }

    //关机
    public void shutdown(PC pc) {
        exitApps();
        pc.shutDown();
    }

    //重启
    public void restart(PC pc) {
        shutdown(pc);
        pc.startup();
    }

    //注销
    public void logOff() {
        exitApps();
    }

    //退出所有正在运行的程序
    private void exitApps() {
        System.out.println("关闭所有正在运行的程序。。。");
    }

把注意力放到方法上。首先构造方法是public的,这样别的地方才能调用它进行实例化。而像开机、关机、重启、注销这些方法都是提供给用户使用的功能自然也必须是public的,那什么方法适合私有化呢。是这样的,如果一个方法是为类里的别的方法服务的时候,那么通常把这个方法定义为私有的。例如例子里的exitApps()就是私有的。因为关机、重启、注销都会关闭所有程序,但是把把关闭所有程序重复写就太冗余了。

改一下测试代码:

    OS myOS = new OS();
    myOS.setLanguage("中文(简体)");
    myOS.setTimeZone(8);

    PC myPC = new PC();
    myPC.setOS(myOS);
    myPC.startup(); //开机
    myPC.getOS().restart(myPC); //重启
    myPC.getOS().shutdown(myPC); //关机

运行结果:
<pre>
一台新的电脑诞生了。
开机
硬件自检
引导操作系统启动
dos系统启动了
关闭所有正在运行的程序。。。
关机
开机
硬件自检
引导操作系统启动
dos系统启动了
关闭所有正在运行的程序。。。
关机
</pre>

本文代码下载:百度网盘

相关文章

  • Class 的封装及调用-Python教学【StudyQuant

    前言:面向对象的三大特性是指:封装、继承和多态。论Class 的封装及调用 面向对象三大特性 面向对象的三大特性是...

  • 面向对象三大特性

    面向对象 三大特性 封装 封装最好理解了。封装是面向对象的特征之一,是对象和类概念的主要特性。封装,也就是把客观事...

  • Java面试之基础篇

    面向对象的特性 面向对象的三大特性是:封装、继承、多态。 封装 封装就是将一个对象的属性和方法进行封装。同时私有化...

  • OC面向对象

    OC面向对象—封装 一、面向对象和封装 面向对象的三大特性:封装(成员变量)、继承和多态 在OC语言中,使用@in...

  • 面试 | java基础

    面向对象 1、面向对象特征? 封装封装是面向对象的特征之一,是对象和类概念的主要特性。封装,也就是把客观事物封装成...

  • 1.1 封装

    本小节知识: 面向对象三大特性 什么是封装 为什么要进行封装? 封装的好处和原则 1.面向对象三大特性 封装性 继...

  • Java 笔试备战

    面向对象特征: 封装,继承,多态 封装:把属性隐藏,提供公共方法对其访问(private 封装特性的一种)面向对象...

  • 面向对象语言基础

    面向对象语言的特性 面向对象的语言的特性:封装、继承、多态。 面向对象语言的设计原则 面向对象的语言在进行程序设计...

  • 面向对象三大特性(一):封装

    面向对象有三大特性:封装、继承和多态。注意,是面向对象的三大特性而不是Java的三大特性,Java只是面向对象语言...

  • 面向对象核心技术

    面向对象核心技术 面向对象编程有3大基本特性:封装、继承和多态。 (1)类的封装:封装是面向对象编程的核心思想。封...

网友评论

    本文标题:面向对象三大特性(一):封装

    本文链接:https://www.haomeiwen.com/subject/qehuqttx.html