第七章 面向对象的编程

本文深入探讨面向对象编程的核心概念,包括类成员变量、类方法和实例方法。重点讲解接口与枚举类型,强调接口的继承、实现与默认方法。此外,还阐述了继承与重写的原则,以及抽象类和多态的运用。最后,讨论了如何设计不可变类,并分析了何时选择不可变类和可变类。
摘要由CSDN通过智能技术生成

第七章 面向对象的编程

基本概念

类成员变量

  • 所有的类共享这一个变量,static修饰

类方法

  • 在这里插入图片描述
    static修饰,类名调用

实例方法

  • 在这里插入图片描述

实例成员变量

接口和枚举类型

接口

  • 接口之间可以继承与扩展
  • 一个类可以实现多个接口(从而具备了多个接口中的方法)
  • 一个接口可以有多种实现类

接口和类的关系

  • 接口:确定 ADT 规约

    • 不要有具体实现

    • 接口没有构造函数,可以使用静态工厂方法代替

    • 接口是immutable的,那么其实现类也该如此

    • 客户端需要知道接口的具体实现类的名字

    • default方法,在接口中统一实现某些功能,无需在各个类中重复实现它。

    • 在这里插入图片描述

    • 可以定义常量,默认都是public static final

  • 类:实现 ADT,也可以不需要接口直接使用类作为 ADT ,既有 ADT 定义也有 ADT 实现

继承和重写

继承

  • 严格继承

    • 子类只能添加新方法,无法重写超类中的方法
    • 在Java中用关键字final修饰方法实现

重写(Overriding)

  • 相同的函数名,相同的参数,相同的返回值

    • 只要有相同的函数名和参数列表,就认为是重写,此时必须要有相同的返回类型(或者返回类型的实现类或子类型),否则编译不通过
  • 编译时决定能否调用,确定其声明类型中是否有这个函数,运行时调用这个实际类型的方法

  • 父类型中的被重写函数体不为空:意味着对其大多数子类型来说,该方法是可以被直接复用的。

  • 对某些子类型来说,有特殊性,故重写父类型中的函数,实现自己的特殊要求

  • 如果父类型中的某个函数实现体为空(方法名(){没有内容}),意味着其所有子类型都需要这个功能,但各有差异,没有共性,在每个子类中均需要重写。

  • 重写之后,利用super()复用了父类型中函数的功能,并对其进行了扩展,其中构造函数的super()必须是第一条语句,同一个类中,调用构造器可用this()

  • 重写的时候,不要改变原方法的本意

  • 子类中重写方法的可见性高于父类方法

    • 父类public,子类只能public
    • 可见性 public>protected>default>private
  • 抛出的异常只能是父类抛出异常类及其子类的子集

抽象类

  • 抽象方法

    • 有声明,没实现体
    • 关键字 abstract
  • 抽象类

    • 至少一个抽象方法
    • 接口是一个只有抽象方法的抽象类
  • 如果某些操作是所有子类型都共有,但彼此有差别,可以在父类型中设计抽象方法,在各子类型中重写(对比父类型使用空实现体)

多态(Polymorphism)

三种多态

  • 特殊多态

    • 函数重载(Overloading)

      • 多个方法具有同样的名字,但有不同的参数列表

      • 价值

        • 方便 client 调用, client 可用不同的参数列表,调用同样的函数
      • 静态多态

        • 根据参数列表进行最佳匹配
        • 静态类型检查
        • 在编译阶段时决定要具体执行哪个方法 (static type checking)
      • 与之相反,overridden方法则是在运行时进行动态检查

      • 重载规则

        • 必须

          • 相同的函数名
          • 不同的参数列表(有顺序,即使参数类型集合相同,不同顺序也算重载)
        • 可选

          • 相同/不同的返回值类型
          • 相同/不同的public/private/protected
          • 相同/不同的异常
        • 可以在同 一个类内重载,也可在子类中重载(发生在父类和子类之间)

          • 如果在子类型中重载,用父类型的声明是调用不到的,编译器报错
  • 参数化多态

    • 泛型

      • 它能够以通用方式定义函数和类型,以便它基于运行时传递的参数工作,即允许静态类型检查而无需完全指定类型。

      • 泛型编程

      • 泛型的父子关系体现在泛型的包含上

        • List 和 List 无继承关系,前者不是后者的父类

        • List是ArrayList的父类

        • List<?>是所有的父类

          • List<? extends Animal> Animal及其子类 上界通配符
          • List<? super Animal> Animal及其父类 下界通配符
      • 运行时泛型消失了,不能使用 instanceof() 检查泛型类型

      • 不能创建泛型数组

        • Pair[] foo = new Pair[42] 相当于Pair[] foo,可插入Pair类型
  • 子类型多态、包含多态

    • 继承

      • B是A的子类型,那么B是A,A能做的B全能做
      • 子类型的规约不能弱化超类型的规约
      • LSP可替换原则
    • 子类型多态

      • 父类引用不同子类,不同类型的对象可以统一的处理而无需区分,从而隔离了“变化”

      • a.getClass()

        • 获取a运行时的类
      • a instanceof B

        • B只要是a运行时的类或者祖先类都为true

重要的Object方法

toString()

  • 在这里插入图片描述

equals()

  • 在这里插入图片描述
    注意是Object o,否则没有重写

hashCode()

  • 在这里插入图片描述

  • 在这里插入图片描述
    效率较低,但其他方面同样好!

设计好的类

写immutable类

  • 不要提供任何修改器
  • 确保没有方法可以被重写
  • 所有字段有final
  • 所有字段用private
  • 确保mutable部分安全(没有表示暴露)
  • 实现toString(), hashCode(), clone(), equals()方法

什么时候使用immutable

  • 总是,除非有充分的理由不这样做

  • 让小的值的类是immutable

    • 例如自己定义的Color, PhoneNumber, Unit,复制代价不高,不怎么会发生变化的
    • Date是mutable,经常会出错,所以long代替它

什么时候使用mutable

  • 类表示状态发生变化的实体
  • 如果类必须是可变的,则最小化可变性
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值