1.抽象类
(1)抽象类的引出
在代码16.8中,Bird类和Ostrich类有继承关系,Ostrich类中重写了父类Bird中的fly()方法,那么,Ostrich类的对象调用的fly()方法就是Ostrich类中自己定义的fly()方法。
接下来,有另外一种情况:对于Bird(鸟)和Plane(飞机),它们没有直接的继承关系,但是它们是有共通之处的。
【代码16.25】Bird(鸟)和Plane(飞机)的定义
抽象类-1
抽象类-2
在代码16.25中,Bird和Plane是不会有父子关系的,也不会有兄弟关系。但是他们有共通的特征:都有id和name属性;都有相同的introduce()方法;都有fly()方法(但是实现体不同)。
现在我们把Bird和Plane中相同的特征抽取出来,使其成为Flyer(飞行器)父类,Bird和Plane都继承Flyer,因为鸟和飞机都会飞,只是飞的方式不同。
Flyer(飞行器)是抽取所有具体的飞行器特征,而每种具体飞行器的fly()的实现体是不同的,所以Flyer的fly()是写不出实现体的,Flyer是个抽象类,它规定了所有具体的飞行器应该具有的特征。
【代码16.26】Flyer抽象类、Bird(鸟)类、Plane(飞机)类的定义
运行结果:
id:1,name:老鹰
鸟儿:我展翅就可以高飞。
****************
id:2,name:波音747
飞机:滑行-起飞-飞行-降落-着陆-滑行。
在代码16.26第33行的Test16_26类中,go()方法接收的参数是父类Flyer类型,那么在调用的时候就可以接受Bird或者Plane的子类对象。在执行的时候,根据传入的具体类型,动态绑定对应类的fly()方法。所以,同样的go()方法调用不同的对象时,其运行结果不同。
如果又有了新的具体飞行器〔如Cloud云它有自己的fly()实现〕,只需要定义Cloud类,继承自Flye类,实现fly()方法。在Test16_26类中,整个程序结构不需要改变,为go()方法传入Cloud类的对象即可。可以理解为在程序的主干不改变的情况下,可以替换传入的对象类型(Bird、Plane、Cloud),这样提高了程序的可扩展性和可维护性。
(2)抽象类的语法规定
抽象类用来给出一组子类的设计模板,子类可以对父类进行扩展,但必须实现父类中所有的抽象方法,这避免了子类设计的随意性。
抽象类的意义
抽象类的语法规定:
①用abstract修饰的类就是抽象类,抽象类是不能被实例化的。
②抽象方法用abstract修饰,没有方法体;包含抽象方法的类一定是抽象类。
③abstract不能与private、static、final并列修饰一个方法。
抽象类定义的语法格式如下:
抽象类给类定义“模板”,将类进行类型的划分,是用来继承的。
如果继承了抽象类,就必须实现父类中所有的抽象方法,否则,本类也成为抽象类。