day8-Java抽象、枚举、接口

JAVA进一步语言构造

抽象abstract

  • 为防止从一个类中产生实例,可以对类使用 abstract 关键字。

    • 抽象类一般是完全概念性的不可产生任何实例,但可以产生子类来向下延伸。比如:通用的Shape、通用的AbstractRobot类。abstract的东西本身无实际意义,但能帮助结构更加清晰。
  • 抽象方法:没有函数体。这些方法被声明,但不提供具体执行内容。类似C中写在前面的函数头,具体定义在后续进行。

    • 规定:任何非抽象的子类,会强制实现其所有执行方法。——使用户知道list上有哪些方法
    • 也就是说,子类如class Dog extends Animal implements Pet{}为成为具体的、非抽象的子类,必须实现所有从接口执行的、从父类延伸继承的抽象方法,否则会报错。
  • 一般一个抽象的类会包含抽象方法。一个类有一个以上抽象方法的,必须也被定义为抽象类。

abstract class AbstractRobot extends Robot { //由Robot拓展得AbstractRobot,避免Robot产生实例
  abstract void greet(AbstractRobot other);
  abstract void greet(TranslationRobot other);//抽象方法无具体函数体,仅原型
  abstract void greet(CarrierRobot other);
}

在之前三角形例子中,规定二维形状的面积和周长计算方法为抽象(并因此二维形状类成为抽象类)的原因是:

所有形状都有面积和周长,但是每个形状的计算方式都不同。因此,我们无法在TwoDimensionalShape类中编写任何有意义的内容。之后通过@Override,再将抽象方法写具体。

枚举类Enumerated Types

  • 与C相比:Java的枚举类更加类型安全与稳健,也更全能。
  • 枚举是一种特别的class类型。里面都是列举的常量,可以用于声明字段、方法,基础形式简单。
  • 考虑到无法匹配已有列举项、处于Exception的情况,应添加一个【可作为默认值/错误值】的常量项到enum中
    • 此时不能把NULL赋值给enum类FoodGroup的实例,因为空值并不是属于enum类里的一项。
    • 例:把DONOTEAT项添加到public enum FoodGroup里,将DONOTEAT作为所有列举的food以外的默认值/容错值。

使用Enum的情景——罗列出某一类变量的各种变体。

​ 有些形状只有一个变体,比如圆只能是圆。但其他形状,如三角形,有多种不同的变体:等腰、直角、等边三角形等。因此可以创建三角形的一系列子类。但这些子类由于没有创建另外的新属性或新方法,只是对JAVA的遗传性一种滥用——创建许多空文件,是无必要地增加了项目文件系统的复杂度。

​ 使用枚举,可以声明一系列预定义的变量可存值。

image-20210221030757622

多分支if语句判断属于哪种类型时,建议:从特例写到常见例,比如从等边三角形开始到不等边。

接口Interface

接口的使用情景:独立于类的等级体系之外,作为marker来标记某类是否有某个特定特征。可以将接口想成一个合约,类必须遵守它并保证提供一定性质和特点。

  • 接口是JAVA中的一种参考类型,可看成一个(方法上)仅有抽象方法的集合。接口无法实例化,也不包含任何构造函数。是一个关键字。(类似于特殊的抽象类)

    • 如果一个类中,既有抽象方法,又有非抽象方法,那么该类只能定义为抽象类,不能定义为接口;
    • 如果一个类中,只有抽象方法,没有非抽象方法,那么该类可以定义为接口。
  • 接口可能也包含常量、default和static的方法,及嵌套的类型。具体实现的操作只存在于这些default和static的方法中。

    接口(interface)是抽象方法和常量值的定义的集合。

  • 接口描述了一个类要实现的行为。当类实现接口时,它会继承这个接口所有的绝对抽象方法。(多态性相关)

  • 一个类可以实现多个接口,一个接口本身也可以延伸继承多个接口

    • 抽象类/接口的意义:子类可以通过继承多种不同的抽象类/接口处,以实现、表现出不同类型的行为。比如这里的,子类Dog可以表现Pet的行为如拥抱,表现Animal的行为如发声,还可以表现Hunter的行为如打猎等。
      • 不同接口内部的方法名、类名相同重名无影响。因为接口内的抽象方法没有提供函数实现。
abstract class Animal{
 abstract void makeNoise();
}
   
interface Pet{
 void cuddle();	//implicitly abstract
 void makeNoise();//不同接口内部的方法名、类名相同重名无影响,因为这里没有提供函数实现
}
   
class Dog extends Animal implements Pet{
 @Override
 public void cuddle(){	//from Pet
   System.out.println("Smelly cuddle!");
 }
     
 @Override
 public void makeNoise(){	//from Animal
   System.out.println("Woof!");
 }
}

instanchof关键字,可以测试一个对象是否使用了/符合接口。

if(shape instanceof MultiVariantShape) System.out.println("This shape has multiple variants")
else System.out.println("This shape has only one variant")

运行命令 java -ea ... = enable assertions

多重继承Multiple Inheritance

有时必须从几个类中派生出一个子类,继承它们所有的属性和方法。但是这样很危险,所以Java不支持多重继承,Java只支持单向继承。但通过接口,能得到多重继承的效果。

  1. 为什么animal类是抽象类:因为无法实例化animal。比如我们无法判断“animal”的寿命是多久、有多少条腿、能不能飞,因为它只是一个概念性的东西,而对比lion、dog,你可以实例化。
  2. 非抽象子类实现抽象父类的抽象方法,通过@Override来差别化地实现。比如Lion和Tiger实现makenoise( )时发出不一样的声音。
  3. 假设Liger是同时继承Lion和Tiger的子类,但Java只允许单向继承,因此要用到接口。比如对于从Animal继承延伸出去的子类Dog, Cat,同时又是符合Pet类的,Pet类还包括Robot的,可以通过implements Pet执行接口实现,以此将单一类与多个父类相联系起来。
posted @ 2021-02-21 15:52  吃饭睡觉打代码  阅读(92)  评论(0)    收藏  举报