面向对象

304 阅读8分钟

什么是面向对象

  • 面向对象编程(OOP
  • 面向对象编程的本质就是:以类的方式组织代码,以对象的形式封装数据
  • 三大特征:封装、继承、多态
  • 从认识论角度考虑是先有对象后有类,对象,是具体的事物。类,是抽象的,是对对象的抽象
  • 从代码运行角度考虑是先有类后有对象。类是对象的模板

对象的创建和分析

类和对象的关系

类是一种抽象的数据类型,它是对某一类事物整体描述/定义,但是并不能代表某一个具体的事物

  • 动物、植物、手机、电脑...
  • Person类、Pet类、Car类等,这些类都是用来描述/定义某一类具体的事物应该具备的特点和行为。

对象是抽象概念的具体实例

  • 张三就是人的一个具体实例,张三家里的旺财就是狗的一个具体实例。
  • 能够体现出特点,展现出功能的是具体的实例,而不是一个抽象的概念。

对象的创建与初始化

  • 使用new关键字创建对象
  • 使用new关键字创建的时候,除了分配内存空间之外,还会给创建好的对象进行默认的初始化以及对类中构造器的调用
  • 类中的构造器也称为构造方法,是在进行创建对象的时候必须要调用的。并且构造器有以下两个特点:
    1. 必须和类的名字相同;
    2. 必须没有返回类型,也不能写void

构造器

  • 构造器:和类名相同;没有返回值
  • 作用:new本质是在调用构造方法;初始化对象的值
  • 注意点:定义有参构造之后,如果想使用无参构造,需要显示的定义一个无参构造

代码实例:

/**
 * @ClassName Student
 * @Description : 学生类
 * @Author : ZG
 * @Date: 2024-06-18 14:38
 */
public class Student {
    private int age;
    private String name;

    public Student() {
    }

    public Student(int age, String name) {
        this.age = age;
        this.name = name;
    }
}

面向对象的三大特征

封装

  • 我们程序设计要追求“高内聚,低耦合”。高内聚:就是类的内部数据操作细节自己完成,不允许外部干涉;低耦合:仅暴露少量的方法给外部使用。
  • 封装(数据的隐藏):通常,应禁止直接访问一个对象中数据的实际表示,而应通过操作接口来访问,这称为信息隐藏。记住这句话就够了,属性私有,get/set
  • 封装的优点:1.提高程序的安全性,保护数据;2.隐藏代码的实现细节;3.统一接口;4.系统可维护增加了

继承

什么是继承

  • 继承是面向对象对象三大特征之一,可以让类与类之间产生父子关系。
  • 可以把多个子类中的重复代码抽取到父类中,子类可以直接使用,减少代码冗余,提高代码的复用性。

继承的格式

public class 子类 extends 父类{}

继承的好处

子类可以得到父类的属性和行为,子类可以使用; 子类可以在父类的基础上新增其他功能,子类更强大;

继承的特点

  • java只支持单继承,不支持多继承,但是支持多层继承;
  • 每一个类都直接或间接的继承于Object类;

子类到底能继承父类中的哪些内容

成员非私有私有
构造方法不能不能
成员变量
成员方法不能
  • 继承中成员变量的访问特点:就近原则;先在局部位置找,本类成员位置找,父类成员位置找,逐级往上。
  • 继承中成员方法的访问特点:this调用,就近原则;super调用,直接找父类。

继承中构造方法的访问特点

  • 父类中的构造方法不会被子类继承
  • 子类中所有的构造方法默认先访问父类中的无参构造,再执行自己。

为什么?

  • 子类在初始化的时候,有可能会使用到父类中的数据,如果父类没有完成初始化,子类将无法使用父类的数据。
  • 子类初始化之前,一定要调用父类构造方法先完成父类数据空间的初始化。

继承中构造方法的访问特点

  • 子类不能继承父类的构造方法,但是可以通过super调用
  • 子类构造方法的第一行,有一个默认的super()
  • 默认先访问父类中无参构造方法,再执行自己
  • 如果想要方法访问父类的有参构造,必须手动书写

super关键字

  • super理解为:父类的
  • super可以用来调用:属性、方法、构造器

super调用属性和方法

  • 我们可以在子类的方法或构造器中。通过使用super.属性或super.方法的方式,显式的调用父类中声明的属性或方法。但是,通常情况下,我们习惯省略super
  • 当子类和父类中定义了同名的属性时,我们要想在子类中调用父类中声明的属性,则必须显示的使用super.属性的方式,表明调用的是父类中声明的属性。
  • 当子类重写了父类中的方法以后,我们想在子类的方法中调用父类中被重写的方法时,则必须显式的使用super.方法的方式,表明调用的是父类中被重写的方法。

super调用构造器

  • 我们可以在子类的构造器中显示的使用super(形参列表)的方式,调用父类中声明的指定的构造器。
  • super(形参列表)的使用,必须声明在子类构造器的首行。
  • 我们在类的构造器中,针对于this(形参列表)或super(形参列表)只能二选一,不能同时出现。
  • 在构造器的首行,没有显示的声明super(形参列表),则默认调用的是父类中空参的构造器:super()
  • 在类的多个构造器中,至少有一个类的构造中使用了super(形参列表)调用了父类中的构造器

重写

  • 需要有继承关系,子类重写父类的方法
  • 方法名必须相同
  • 参数列表必须相同
  • 修饰符:范围可以扩大但是不能缩小,public>peotected>缺省>private
  • 抛出的异常:范围可以缩小,但是不能扩大
  • 重写,子类的方法和父类必要一致;方法体不同
  • 为什么需要重写:父类的功能,子类不一定需要,或者不一定满足

父类中不能被重写的方法

  • static修饰的方法(static方法属于类,不属于实例)
  • final修饰的方法(final常量修饰符)
  • private修饰的方法,私有的方法不能重写

多态

定义:

  • 多态是同一个行为具有不同的表现形式或形态的能力
  • 同一方法可以根据发送的对象的不同而采用不同的行为方式

多态就是事物的多种形态,一个对象在不同条件下所表现的不同形式

多态的存在条件:

  1. 继承或是实现:在多态中必须存在有继承或实现关系的子类和父类
  2. 方法的重写:子类对父类中的某些方法进行重新定义(重写,使用@Override注解进行重写)
  3. 基类引用指向派生类对象,即父类引用指向子类对象,父类类型:指子类对象继承的父类类型,或实现的父接口类型

多态的格式:

  • 父类类型 变量名=new 子类型();
  • 然后通过 变量量.方法名()调用在子类重写的方法
  • 多态体现为父类引用变量可以指向子类对象:定义了一个父类类型的引用,指向新建的子类类型的对象,由于子类是继承他的父类的,所以父类类型引用是可以指向子类类型的对象的
public class Test01 {
    public static void main(String[] args) {
        Person student = new Student();
        student.eat();
    }
}

多态中的成员特点:

多态成员变量:编译运行看左边 多态成员方法:编译看左边,运行看右边

多态的特点:

  • 子类和父类存在同名的成员变量时,访问的是父类的成员变量
  • 子类和父类存在同名的非静态成员方法时,访问的是子类中重写的方法
  • 子类和父类存在同名的静态成员变量成员方法时,访问的是父类的成员函数
  • 不能访问子类中独有的方法

引用类型转换:

  • 向上转型:子类向父类向上转换(自动转换)的过程,这个过程是默许的,当父类引用指向子类对象时,就是向上转型
  • 向下转型:向下转型是父类向子类转换的过程,这个过程需要强制转换
  • 向下转型的问题:虽然可以通过向下转型可以调用子类独有的方法,但也会产生下面的问题ClassCastException类型转换异常。想要避免这种问题就要使用instanceof关键字。
public class Test01 {
    public static void main(String[] args) {
        //如果变量student属于该数据类型或者是其子类,返回true
        //如果变量不student属于该数据类型或者是其子类,返回true
        Person student = new Student();
        boolean flag = student instanceof Person;
    }
}