6、面向对象的特性

107 阅读5分钟

封装、继承、多态

一、封装

生活中的封装:包装盒、机箱

代码中的封装:类、方法、包

好处:

  1. 提高了复用性
  2. 隐藏了实现细节
  3. 提高了安全性

问题:只要对属性的赋值在指定类型的范围内,程序就能正常运行,但是数据却是不合理的

原因:没有对数据进行合理性的判断

通过对属性的封装来解决该问题,解决步骤:

  1. 使用关键字private来修饰属性,

    private用来修饰成员,被private修改的成员只能在本类中访问

  2. 对外提供这个私有属性的访问方法:get/set

    // set
    public void setAge(int age){
        if(age >= 0 && age <= 120){
            this.age = age;
        }
    }
    ​
    // get
    public int getAge(){
        return this.age;
    }
    

注:

  1. 如果被封装的属性是布尔类型:get/set一般会写成is/set

  2. JavaBean的标准定义:

    1. 无参构造函数
    2. 私有化的属性
    3. 私有属性对外提供的set/get方法

二、继承

2.1、概念

继承让类与类之间产生了联系,称为子类继承父类

好处:

  1. 提高了代码的复用性
  2. 为多态提供了前提

注:

  1. 继承关系中的父类(superclass)也叫超类、基类;子类(subclass)也叫派生类、衍生类
  2. Object类是所有类的父类,任何类都直接或者间接的继承了Object
  3. 父类的范围比子类大,但是属性和方法比子类少,子类除了有父类中的共性内容外,还可以有特性内容
  4. 一个子类就是一个父类

2.2、继承关系

关键字:extends

public class 父类{
​
}
​
public class 子类 extends 父类{
​
}

注:

  1. 子类可以继承父类中的所有非私有成员
  2. 一个父类可以有多个子类
  3. 一个子类只能有一个父类,类与类之间只存在单继承
  4. 类与类之间存在多层继承

2.3、继承关系中成员的同名问题

同名成员变量:根据就近原则优先访问子类中

同名成员方法:根据就近原则优先访问子类中

方法的重写(override):在继承关系中,子类方法的方法名与父类方法的方法名相同,且参数列表也相同称为方法的重写,可以用注解@Override来检验是否是重写

重写也叫复写、覆盖

方法重写的意义:扩展子类功能

1. 子类重写父类方法的范围修饰符要大于等于父类的
2. 子类重写父类方法的返回类型必须是父类方法的返回类型或者该类型的子类

2.4、父类属性私有化的问题

子类的共性属性抽取到父类中,父类作为一个JavaBean,其中的属性都是私有的,那么子类无法访问。

子类可以通过父类中私有属性对外提供的set/get方法来访问这些私有属性

如何在创建子类对象的同时,为子类的共性属性进行初始化?

// 在子类的重载构造函数中调用父类的重载构造函数
public Programmer(String id, String name, int age, double salary){
 super(id,name,age,salary);
}

此时如果还需要为子类的特性属性进行初始化,可以添加重载构造函数

private double money;
​
public Programmer(String id, String name, int age, double salary,double money){
 super(id,name,age,salary);
 this.money = money;
}

2.5、关键字this、super

this可以访问:

  1. 本类的成员变量

  2. 本类的成员方法

  3. 本类构造函数

    this(参数);
    

    注:调用本类构造函数的语句必须是构造函数中的第一条语句

super可以访问:

  1. 父类的成员变量

  2. 父类的成员方法

  3. 父类的构造函数

    注:每一个类的每一个构造函数中的第一行都默认调用了父类的无参构造函数

三、多态

3.1、概念

多态的前提:必须要有继承关系

代码中体现:父类的引用变量指向子类对象

父类 对象名 = new 子类();

3.2、多态下,调用成员的特点

调用成员变量的特点:编译期间,父类中有这个变量编译通过,父类中没有这个变量编译失败;运行期间,访问的是父类中的变量

多态下不能访问子类的特有成员变量

调用成员方法的特点:编译期间,父类中有这个方法编译通过,父类中没有这个方法编译失败;运行期间,访问的是子类中的方法

多态下不能访问子类的特有成员方法

简单记忆:

调用变量:编译运行都看左边

调用方法:编译看左边运行看右边

3.3、多态的好处

应用场景1:如果一个方法的形参是引用数据类型,那么实参可以是这个引用类型的对象或者它的任何一个子类对象

应用场景2:如果一个方法的返回类型是引用数据类型,那么返回的结果可以该类型对象或者它的任何一个子类对象

3.4、多态的转型问题

向上转型:多态的本质就是向上转型,父类的引用变量指向子类对象

弊端:多态下无法访问子类的特有内容

解决办法:向下转型

向下转型:将一个多态下的引用变量强制类型转换成指定的子类

父类 父类引用变量 = new 子类();
子类 子类引用变量 = (子类)父类引用变量;

注:如果强转的类型与原多态下对象的类型不一致会发生ClassCaseException类型转换异常

关键字:instanceof

对象名 instanceof 数据类型

运行的结果是一个布尔值,如果对象属于指定类型返回true,否则返回false