Java 语言-6 面向对象编程

6.1 认识面向对象

  • 面向过程 & 面向对象
    • 面向过程的思想:步骤清晰简单;合适处理一些较为简单的问题
    • 面向对象的思想:以分类的思维模式处理问题;合适处理复杂的问题,适合处理多人协助问题
    • 对于描述复杂的事物,为了从宏观上把握,从整体上合理分析,我们需要使用面向对象的思路来分析整个系统。到了具体微观操作,我们仍需要面向过程的思路去处理问题
  • 面向对象编程(Object Oriented Programming,OOP)
    • 本质:以类的方式组织代码,以对象的组织(封装)数据
    • 编程思想:抽象
    • 三大特性:封装、继承、多态
  • 设计思想的要点
    • 认为客观世界由各种对象组成
    • 程序的分析和设计都围绕着:有哪些对象类;每个类有哪些属性、方法;类之间的关系(继承、关联……);对象之间发送消息(调用方法)等进行
  • 理解:
    • 从认识论角度考虑是先有对象后有类
    • 从代码运行角度考虑是先有类后有对象

6.2 面向对象三大特征

6.2.1 封装

  • 封装:是类对象的状态和方法,就是将字段和方法封装在一个类中

  • 封装:主要是模块化和信息隐藏两个方面

    • 模块化:将属性和行为封装在类中,程序定义多个类
    • 信息隐蔽:将类的细节部分隐藏起来,用户只通过保护的接口访问某个类
  • 封装可用于完成程序设计要追求的“高内聚,低耦合”

    • 高内聚:类的内部操作细节,不允许外部干涉
    • 低耦合:仅暴露少量方法给外部
  • 方法:使用 private 关键字对类或者成员进行封装,再使用 setXXX() 和 getXXX() 方法对类的属性进行存取,分别称为 setter 和 getter

    • 示例:

      class Person{
          private int age;
          public void setAge(int age){
              if(age>0 && age<200)this.age = age;
          }
          pubilc int getAge(){
              return age;
          }
      }
      
    • 简单记忆:属性私有,get/set

  • 实现快速封装快捷键(IDEA):Alt+Insert

  • 意义:

    1. 更好的封装和隐藏,使外部类不能随意存取修改,提高程序的安全性,保护数据
    2. 隐藏代码的实现细节
    3. 统一接口
    4. 增加系统的可维护性

6.2.2 继承

  • 继承:指父类和子类之间共享的数据和方法

    • 子类(subclass),父类或超类(superclass)
      • 父类包括所有直接或间接被继承的类
    • 除此之外类和类之间还有依赖、组合、聚合等关系
  • Java 中类只有单继承,没有多继承

    • 接口可以多继承
  • 意义:

    • 子类可以继承父类的状态和行为
    • 可以修改父类的状态或者重载父类的行为
    • 可以添加新的状态和行为
  • 作用

    1. 更好进行抽象和分类
    2. 增强代码的复用率,提高开发效率和可维护性
  • Java 实现继承是通过 extends 关键字,意思是“扩展”

    • 例如:

      public class Student extends Person{
          ……
      }
      
    • 如果没有 extends 子句,则默认为继承于 java.lang.Object

      • 所有的类都是直接或者间接继承 Object 类
  • 继承关系:相当于 is 关系

  • 字段

    • 字段的继承:子类可以继承父类的所有字段
    • 字段的隐藏:子类重新定义一个从父类那里继承来的变量完全相同的变量,称为域的隐藏
      • 在实际应用中较少
    • 字段的添加:在定义子类时,加上新的域变量
      • 在实际应用中较多
  • 方法

    • 方法的继承:父类非私有方法也可以被子类自动继承
    • 方法的覆盖:也称为方法重写,子类也可以重新定义与父类同名的方法,实现对父类方法的覆盖
    • 方法的添加:子类可以新加一些方法
      • 方法重载是特殊的方法的添加
  • 判断两个对象之间的关系使用 instanceof 关键字

    • 如果有继承关系返回 True,否则返回 False

    • 示例:

      object instanceof Student
      
  • 查看继承关系快捷键(IDEA):ctrl+H

  • 在子类访问父类属性和方法使用 super 关键字

    • 例如:调用父类 name 属性

      super.name
      
    • 注意点:

      1. super 调用父类方法,必须位于构造方法第一行
      2. super 只能出现在子类的方法或者构造方法中
      3. super 和 this 不能同时调用构造方法
    • 与 this 对比

      super this
      代表对象 代表父类对象的应用 代表调用者这个对象
      前提 只能在继承条件下使用 没有显式继承条件也可以使用
      构造方法 父类的构造 本类的构造
  • 方法重写

    • 是重写方法,与属性无关
    • 在 JDK 1.5 后可以使用 @Override 标注表示进行了方法重写
    • 重写后父类调用该方法,是实现的子类的方法,而不是父类的方法
    • 重写快捷键(IDEA):Alt+Insert
    • 要求:
      1. 需要有继承关系,子类重写父类的方法
      2. 方法名、参数列表必须相同,方法体不同
      3. 修饰符范围:可以扩大,不能缩写
        • \(pubilc>protected>default>private\)
      4. 抛出异常范围:可以缩小,不能扩大
        • \(ClassNotFoundException<Exception\)
    • 用途:
      • 父类的功能子类不一定需要或不一定满足

6.2.3 多态

  • 多态是指不同对象收到同一个消息(调用方法)可产生不同的效果,其实现的细节则由对象自行决定
  • 多态可实现动态编译,增强可扩展性
  • 实现要求:
    1. 父类与子类有继承关系
    2. 方法需要重写
      • 有些方法不能重写:static、final、private
    3. 父类引用指向子类对象
  • 注意点:
    1. 多态是方法的多态,属性没有多态
    2. 父类与子类有关系
      • 如果没有关系会发生类型转换异常:\(ClassCastException\)

6.3 super 的使用

  • 使用 super 访问父类的变量和方法

    • 也可以使用 this 来访问父类的域和方法

    • 例如:假设有一个类的父类有 age() 方法 ,在该类中使用 age()

      void testThisSuper(){
          int a;
          a = age;
          a = this.age;
          a = super,age;
      }
      

      这三种访问结果均相同

    • 为什么有了 this 还需要使用 super

      • 有些时候为了明确地指明父类的变量和方法
      • 访问被子类所隐藏的同名变量
      • 当覆盖父类方法的同时,又需要调用父类的方法
  • 使用父类的构造方法

    • 构造方法与类名相同,是不能继承的

      • 不能说父类(例如:Person)有一个构造方法(Person())子类(例如:Student)也自动有一个构造方法(Student())
    • 但是可以通过 super 来调用父类的构造方法

    • 例如:父类 Person 的构造方法 Person(String name, int age),子类调用

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

      使用时,super() 语句必须放在第一句

6.4 类型转化

  • 这里是指父类对象与子类对象的转化,与基本数据类型的转换类似

    • 子类对象可以被视为其父类的一个对象

      • 例如:一个 Student 对象可以被视为一个 Person 的对象
    • 父类对象不能视为子类对象

  • “低”转“高”自动转换:如果一个方法的形式参数定义的是 父类对象,那么调用这个方法时,可以使用子类对象作为实际参数

    • “低”指父类级别,“高”指子类级别

    • 例如:Person 是 Student 的父类

      Person student = new Student();
      
  • “高”转“低”强制转换:如果父类对象引用指向的实际是一个子类对象,那么这个父类对象的引用可以使用强制类型转换成为子类的引用

    • 转换方法与基本类型类型转换类似:在对象前添加()

    • 例如:

      Person student = new Student();
      Stuednt obj = (Student) sutdent;
      
      • 可能会丢失一些本来的方法
    • 存在意义:方便方法调用,减少重复代码,简洁

  • 类型转换条件

    1. 父类引用指向子类对象
    2. 把子类转换为父类,向上转型,自动转换
    3. 把父类转化为子类,向下转型,强制转换

6.5 接口

  • 接口就是规范,定义的是一组规则;

    • 本质就是契约;OO 的精髓,是对对象的抽象最能体现的一点
    • 也是一种引用类型
  • 接口 & 普通类 & 抽象类

    • 普通类:只有具体实现
    • 抽象类:具体实现和规范(抽象方法)都有
    • 接口:只有规范
  • 声明接口使用 interface 关键字,声明之后的方法都自动是 public abstract

    • 定义的时候 public、abstract 两个关键字是可以省略的

    • 声明类的关键字是 class

    • 例如:接口的简单操作

      public interface UserService{
          void add(String name);
          void delete(String name);
          void update(String name);
          void query(String name);
      }
      

      在接口中很多东西是看不见的,所以可以直接用返回值类型、方法名以及参数列表即可定义

  • 使用 implements 实现接口。实现接口,就必须要实现接口全部的方法

    • 实现类一般命名以 Impl 结尾

    • 例如:实现接口 UserService

      pubilc class UserServiceLmpl implements UserService{
          ……
      }
      
    • 接口可以多继承,从而侧面实现多继承

  • 要点:

    1. 约束
    2. 可以实现不相关类的相同行为,而,不需要考虑这些类之间的层次关系。一定意义上实现多继承
    3. 接口不能被实例化,接口中没有构造方法
    4. 可以实现多个接口
    5. 实现接口必须重写全部方法
  • 接口中的常量

    • 接口中主要是抽象方法,但是也存在常量

    • 格式:

      type NAME = value;
      

      type:可以为任意类型

      NAME:为常量名,通常为大写

      value:为常量值

    • 在接口定义的常量可以被实现该接口的多个类共享

      • 与 C 中 #define 和 C++ 中的 const 定义的常量相同
    • 接口中定义的常量具有 public、static、final 属性,通常省略

  • 在 java 8 中的接口

    • 在Java 8 中新添加了 static 方法
    • 具有实现体的方法(default 方法)
      • 默认方法的用途:提供了一个默认实现。子类在 implements 可以不用重新写实现方法
posted @ 2022-02-17 19:57  你是我的生命之源  阅读(73)  评论(0)    收藏  举报
页脚