Java——面向对象进阶(封装、继承、多态)

Java面向对象三大特性——封装、继承、多态

  • 一、封装
    • 1.封装基本概念
    • 2.访问修饰符
    • 3.Java中封装的理解
    • 4.封装的优点
  • 二、继承
    • 1.为什么需要继承
    • 2.继承层次结构
    • 3.super和this关键字
    • 4.继承语法与设计一个继承体系
  • 三、多态
    • 1.多态的概念
    • 2.多态的实现条件
    • 3.多态的优缺点

一、封装

1.封装基本概念

封装(encapsulation,有时称为信息隐藏)是处理对象的一个重要概念。
从形式上看,封装就是将数据和行为组合在一个包中,并对对象的使用者
隐藏具体的实现细节。对象中的数据称为实例字段(instance field),
操作数据的过程称为方法(method)。作为一个类的实例,一个特定对象
就有一组特定的实例字段值。这些值的集合就是这个对象当前的状态(state)
只要在对象上调用一个方法,它的状态就有可能发生改变。

封装的关键:
绝对不能让其他类中的方法直接访问这个类的实例字段。程序只能通过对象的方法与对象的数据进行交互。

2.访问修饰符

下面是小编整理的访问限定符,这是一定要掌握的哦

No 范围 private default protected public
1 同一包中的同一类
2 同一包中的不一类
3 不同包中的子类
4 不同包中的非子类

3.Java中封装的理解

我们在设计程序的时候追求高内聚、低耦合
高内聚——类的内部数据的操作和细节自己完成,不允许外部干涉;
低耦合——对外提供少量的公共方法使用

我们在实现的一个类的时候隐藏类内部的复杂性、之对外提供简单的公开的接口。便于外界调用从而提高系统的可拓展性、可维护性,这里就要讲到Java中权限访问修饰符(private、默认(什么都不加)、protected、public)进行封装。

下面我们用封装的思想来编写一个员工类
属性——姓名、年龄、工资
行为——上班摸鱼

public class Employee {
    /**
     * 将特有的属性进行封装,并且不希望外界随意
     * 的对他进行修稿,这里我们就要用到私有的访
     * 问修饰符——private
     */
    private String name;
    private int age;
    private double salary;

    //构造方法,供外界实例一个类对象来操作数据
    public Employee(String name,int age,double salary) {
        this.name = name;
        this.age = age;
        this.salary = salary;
    }

    /**
     * 对外提供少量的公共方法供实例对象来操作数据
     * 主要是get、set方法,就比如说有一天我的员工修
     * 改了姓名或者调薪
     */
    //set设置器
    public void setName(String name) {
        this.name = name;
    }

    public void setAge(int age) {
        this.age = age;
    }

    //get访问器
    public String getName() {
        return name;
    }

    public int getAge() {
        return age;
    }

    public double getSalary() {
        return salary;
    }

    //特有的行为
    public void work() {
        System.out.println("名字为" + name + "的员工正在上班摸鱼");
    }

    public void raiseSalary(double byPercent) {
        double raise = salary * byPercent / 100;
        salary += raise;
    }
}

4.封装的优点

最后我们再仔细看一下非常简单getName、getSalary方法

public String getName() {
	return name;
}

public double getSalary() {
	return salary;
}

这些都是典型的访问器。由于他们只返回实例字段的值,因此又称为字段访问器(field accessor)。

如果将name、salary字段标记为公共,而不是编写单独的访问器方法,不是更容易一些吗?

不过name只是一个只读字段,一旦再构造器(构造方法)中设置,就没有办法能够修改这个字段。这样我们就可以确保name字段不会受到外界的破坏。

虽然salary不是只读字段,但是它只能用raiseSalary方法修改。具体的,如果这个值发生错误,那么只需要调试这个raiseSalary方法就可以了。如果salary字段是公共的,破坏这个字段的罪魁祸首就可以出现再任何地方(那就很难调试了)。

二、继承

1.为什么需要继承

让我们回忆一下上面讨论的employee类。假设你在某个公司工作,这个公司里经理的待遇与普通员工的待遇存在着一些差异。不过,当然他们当中也存在很多相同的地方,例如,他们都领取薪水。只是普通员工在完成本职任务后仅领取薪水,而经理在完成了预期的业绩之后还能得到奖金。这种情形就需要使用继承。
为什么呢?因为需要为经理定义一个新类Manager,并增加一些新功能,但可以重用Employee类中已经编写好的部分代码,并保留Employee类中的所有字段。

**继承机制:**是面向对象程序设计使代码可以复用的重要手段,它允许程序员在保持原有类特性的基础上进行拓展,这样产生新的类,称派生类。继承呈现了面向对象程序设计的层次结构,体现了由简单到复杂的认知过程。继承主要解决的问题是:共性的抽取,实现代码复用。

2.继承层次结构

继承并不仅限于一个层次。例如,可以由Animal类派生出狗类、猫类、鸟类,再由猫类派生出中华田园猫、英国短毛猫、布偶猫等。由一个公共超类派生出来的所有类的集合称为继承层次结构(inheritance hierarchy),如下图所示。再继承层次结构中,从某个特定的类到其祖先的路径称为该类的继承链(inheritance chain)。

补充:
在C++中,一个类可以有多个超类。Java不支持多重继承,但支持多层继承。

Java——面向对象进阶(封装、继承、多态)_第1张图片

3.super和this关键字

由于设计不好,或者因场景需要,子类和父类中可能会存在相同名称的成员,如果要在子类方法中访问父类同名成员时,该如何操作?直接访问是无法做到的,Java提供了super关键字,该关键字主要作用:在子类方法中访问父类的成员。
this关键字主要在本类访问本类成员成员变量,**该关键字的主要作用:**在本类方法中访问本类的成员
super和this都可以在成员方法中用来访问:成员变量和调用其他的成员函数,都可以作为构造方法的第一条语句,他们之间有什么区别呢/?
【相同点】
1.都是Java中的关键字
2。只能在类的非静态方法中使用,用来访问非静态的成员方法和字段
3.在构造方法中调用时,必须时构造方法中的第一条语句,并且不能不能同时存在
【不同点】
1.this是当前对象的引用,当前对象即为调用实例方法的对象,super相当于是子类对象中从父类继承下来部分成员的引用
2. 在非静态成员方法中,this用来访问本类的方法和属性,super用来访问父类继承下来的方法和属性
3. 在构造方法中:this(…)用于调用本类构造方法,super(…)用于调用父类构造方法,两种调用不能同时在构造
方法中出现
4. 构造方法中一定会存在super(…)的调用,用户没有写编译器也会增加,但是this(…)用户不写则没有

4.继承语法与设计一个继承体系

4.1 继承语法:
Java中如果要表示类之间的继承关系,需借助extends关键字,具体如下:

修饰符 class 子类名 extends 父类名 {
	//...
}

4.2 设计一个继承体系
父类Employee类:
属性——姓名、年龄、工资
行为——上班摸鱼、调薪
子类Manager类:
属性——姓名、年龄、工资、奖金(特有的)
行为——看看谁摸鱼、调薪

class Employee {
    //属性
    private String name;
    private int age;
    private double salary;

    //构造方法
    public Employee(String name,int age,double salary) {
        /**this关键字的用法解释
         * 由于方法形参与成员变量同名,不适用this关键字就造成变量
         * 同名,不使用this关键字就遵循就近原则,影响不到成员变量
         * 故this.name指定了成员变量的name,而非形参的name
         */
        this.name = name;
        this.age = age;
        this.salary = salary;
    }
    //set更改器
    public void setName(String name) {
        this.name = name;
    }

    public void setAge(int age) {
        this.age = age;
    }

    //get访问器
    public String getName() {
        return name;
    }

    public int getAge() {
        return age;
    }

    public double getSalary() {
        return salary;
    }

    //行为
    public void work() {
        System.out.println("名字为" + name + "的员工正在上班摸鱼!");
    }

    public void raiseSalary(double byPercent) {
        double raise = salary * byPercent / 100;
        salary += raise;
    }
}

class Manager extends Employee {
    //属性,与父类相同的属性就不必写了,这就是继承的好处
    private double bonus;

    public Manager(String name, int age, double salary) {
        /**super关键字用法的解释
         * 因为这个类继承了Employee类,必须帮助父类构造
         * 这里的super是调用了父类的构造方法
         */
        super(name, age, salary);
        //这里的奖金并不是构造对象时马上给出的,根据业绩的给定的
        this.bonus = 0;
    }

    /*由于父类的访问器已经不能满足子类的需求了,故需要重写
    父类的getSalary()方法,这里不加拓展重写,有关内容期待博主更新
    或者网上查阅资料哦!!!*/
    public double getSalary() {
        //这里super关键字的用法时调用父类的成员方法
        double baseSalary = super.getSalary();
        return baseSalary + bonus;
    }

    public void setBonus(double bonus) {
        this.bonus = bonus;
    }

    public void superviseWork() {
        System.out.println("名为" + super.getName() + "正在看看谁上班摸鱼!");
    }
}

三、多态

1.多态的概念

在Java程序设计语言中,对象变量时多态的(polymorphic)。一个Employee类型的变量既可以引用一个Employee类型的对象,也可以引用Employee类的任何一个子类的对象(例如:Manager)。
那就意味着我们可以这样用,接上面的继承篇

Manager boss = new Manager("张三",24,12000);
Employee[] staff = new Employee[3];
staff[0] = boss;
boss.setBonus(5000)//OK
staff[0].setBonus(5000)//ERROR

为什么会发生错误呢?这是因为staff声明是Employee类型,Employee类中并没有setBonus()方法,boss则是声明为Manager类型,类中有setBonus()方法,所以调用时正确的。

**多态的概念:**通俗来说,就是多种形态,具体点就是去完成某个行为,当不同的对象去完成时会产生不同的状态。

2.多态的实现条件

在Java中要想完成多态,必须要满足如下几个条件,缺一不可:

  • 必须在继承体系下
  • 子类必须要对父类中的方法进行重写
  • 通过父类的引用调用重写的方法

**多态体现:**在代码运行时,当传递不同类对象时,会调用对应类中的方法。

Employee boss = new Manager("张三",24,12000);
/**
*此时父类和子类中都有setSalary()方法,编译器在编译代码时并不知道
*要调用Employee中的方法还是Manager中的方法,等程序运行起来后,变量
*boss引用的具体对象确定后,才知道要调用那个方法。明显这里boss引用
*Manager,所以回调用Manager类中的getSalary方法。
*/
boss.getSalary();

3.多态的优缺点

1.多态的优点

  • 能够降低代码的复杂度,避免大量使用if-else
  • 拓展能力更强

2.多态的缺陷

  • 属性没有多态性
当父类和子类都有同名属性的时候,通过父类引用,只能引用父类自己
的成员属性
  • 构造方法没有多态性

结语:每个人的成长和进步都离不开点点滴滴的积累,如果小编的内容对您有所帮助,希望友友们三连加关注哦,你的支持是小编创作的最大动力。

你可能感兴趣的:(java,开发语言)