【MIT软件构造】ADT Patterns: Interfaces, Generics, and Enums

接口(Interfaces)

基本概念不再赘述,值得注意(记住)的有几点:

  1. 接口不应该有构造函数
  2. 只有静态方法才能拥有方法体
  3. 接口实现不能破坏表示不变性
    【MIT软件构造】ADT Patterns: Interfaces, Generics, and Enums_第1张图片
  4. 接口实现可以添加接口没有的方法,但是不能缺少接口声明的方法
  5. 接口实现不应该违背接口规约(比如接口规约声明为不可变类型,但在实现类里加入了mutator)

子类型(subtype)

a是b的子类型,则a要么implement b,要么extend b。
a是b的子类(subclass),则a extend b。
(随着接口的提出,java似乎是第一个跳出来说出子类型与子类是有区别的语言,并在某种意义上不鼓励继承,而推崇接口与实现。关于子类和子类型的区别笔者还理解不够,读者大可选择无视
思考一个问题,ArrayList是可变的,List.of()是不可变的,它们都是List的合法子类型,那么List到底是可变还是不可变的呢?
答案是模糊的,事实上List、Map、Set等接口的规约中对此接口ADT到底是可变还是不可变的并没有明确的声明。同时要注意的是,子类型的规约强度应高于产生子类型的类型的规约强度(precondition变弱或postcondition变强)

泛型(Generic Types)

泛型的提出让java设计的重用性变得更上一层楼,它与接口相互结合,让java拥有了自己的特色。

接口的好处

  1. 接口可以让编译器帮忙检查ADT(实现类)的明显错误
  2. 提供多种功能,不同实现方法在不同操作上可能效率不同

子类(Subclass)与继承

继承父类与实现接口的区别在于rep也会从父类传到子类,但是非严格继承是容易产生错误的(此部分原文没有)

  1. final对继承的影响:

final修饰父类方法,子类无法重写
final修饰父类,不能继承

  1. 非严格继承:子类中重写了父类的方法(难保证语义没有改变)

辨析下面的例子
【MIT软件构造】ADT Patterns: Interfaces, Generics, and Enums_第2张图片
运行下面的代码,结果分别是什么?
【MIT软件构造】ADT Patterns: Interfaces, Generics, and Enums_第3张图片
第一块:正确
第二块:正确,因为Horse中有来自父类的eat()方法
第三块:正确
第四块:正确
第五块:错误
第六块:错误!ah2虽然是指向Horse的引用,但本身是Animal类,并没有eat(String s)方法

初学者很容易出现第第六块的错误,解决方法如下:
1、直接用Horse类声明,就像第四块
2、向下转型,原则上第六块的错误是向上转型导致的
3、在Animal类中声明eat(String s)方法

但如果是重写eat方法
【MIT软件构造】ADT Patterns: Interfaces, Generics, and Enums_第4张图片
【MIT软件构造】ADT Patterns: Interfaces, Generics, and Enums_第5张图片
调用的却是Horse中的eat方法
【MIT软件构造】ADT Patterns: Interfaces, Generics, and Enums_第6张图片

你可能感兴趣的:(java与软件构造)