在具体到抽象类和接口的问题之前,需要先说说“继承”相关的问题
继承
什么是继承
首先我们都直到(我默认大家都知道),“继承”是面向对象里的一个概念,是面向对象最大的特点之一(封装 继承 多态)。继承(inheritance)可以使得子类具有父类的属性和方法或者重新定义、追加属性和方法等。
其实顾名思义,所谓继承就是子可以从父那里直接得到一些东西。
放在面向对象里,就是子类可以直接继承父类的成员变量和方法(不过得是public的)
Java继承是使用已存在的类的定义作为基础建立新类的技术,新类的定义可以增加新的数据或新的功能,也可以用父类的功能。
举个例子,一个类Animal有体积、年龄、所属的界门纲目、吃什么食物等属性,有移动、进食等方法。
现在我就可以搞一个类Tiger继承Animal,一个狮子类继承animal,一个类啄木鸟继承Animal,这三个子类继承自Animal,不需要自己单独去声明,就已经继承了Animal里定义的特征和行为。
子类和父类之间是一种“Is A ”关系。
比如 tiger is an animal
lion is an animal
man is a person等等
在Java里,表示继承的关键字是extends
(C++里是 子类: public 父类; python里是 class 子类(父类): )
另外,JAVA中所有的类都默认是继承自Object类的,都包含Object中定义的方法,比如一个snowBoard类:
为什么要继承
这题要回答继承的优点。
很明显:
- 1)子类可以直接继承父类的特征和行为,那就避免要写重复的代码。
在单一的位置定义共同的程序代码,然后让子类去继承。当需要修改时,只需要改父类,所有的子类就会跟着一起改变。 - 2)灵活性可拓展性较高,可以对某个子类单独修改定制特定的属性和方法,而不会影响到其他的子类。 比如我可以在啄木鸟里加个属性叫最多飞多高,老虎狮子是不受影响的; 同时由于子类可以设置自己独特的属性值,而且可以改变、覆盖、重载父类的方法,从而不同的子类可以拥有各种多样性。
- 3)定义出共同的“协议”。继承让你可以确保某个父类之下的所有子类都会有父类所持有的全部方法。相当于一种共同协议,这为多态提供可能。比如我们声明一个Animal数组,其中可以放老虎可以放狮子也可以放啄木鸟的instance,而且我能确定他们都能调用到eat()方法,虽然他们吃的不一样,但都有
比如老虎狮子啄木鸟要各自覆盖一下从父类继承来的“eat()”方法,因为确实大家吃的很不一样。 // 想想如果是过程式代码,虽然一开始只写一个eat方法,但是老虎加了需求可能就会影响到啄木鸟。(也就是说,多态的情况下,引用与对象可以是不同的类型,Animal的引用变量可以指向Tiger对象。)
好的继承里,应该抽象出合适的共同特征和方法放到父类里,其他的交给子类去扩充。通常父类是比较抽象的,子类是比较具体的。
抽象类
什么是抽象类
抽象类是不能实例化的类,只能被继承,Java中用abstract关键词修饰(C++中用的是virtual关键字)。
为什么需要抽象类
1、有些类不应该被实例化。比如 Animal实例一下,它的属性得长啥样?哺乳动物类实例一下,它的进食方法应该怎么样?
很明显老虎狮子这种是具体类,相比之下Animal是抽象的,不应该被实例化。
2、有时候确实没必要去实现父类的方法,因为反正所有的子类都会各自实现自己的。
abstract关键字标记的类就不能实例化出对象了,继承它的子类必须要实现其中所有abstract标记的方法。
不过抽象类中是可以有抽象的方法也可以有具体的方法的。但是一旦有了抽象的方法,这个类就得是抽象类。不然万一实例化一个对象,想要调用这个没有函数体的抽象方法该怎么办!
接口
什么是接口
接口是一种用来定义程序的协议,它描述可属于任何类或结构的一组相关行为。
为什么要用接口
1、接口的意义在于 抽象、不拘细节,从而使同类事物在同一高度具有通用及可替代性。
2、很现实,Java不支持多继承,一个类只能有一个父类。那如果一个类既需要继承某个类的一些公共功能,也要继承另一组公共功能呢?那就只能继承一个,另一个得通过实现接口了。
关于为什么Java不支持多继承,因为可能出现“致命方块”的问题。比如下面这个图中,中间两个类各自override了父类同一个方法,那同时继承这两个类的子类调用这个方法的时候,到底要调用哪一个呢?
在Java中用Interface关键字来标识接口,实现接口用关键字implements
接口与抽象类异同
同:
- 都不能实例化
- 都可以被继承
- 都可以声明方法
- 子类必须要实现其中全部的abstract方法
异: - 抽象类可以包含具体的方法,但接口中只能是抽象的方法
- 接口中不能有构造函数(很显然
- 接口里的方法都是public的,但抽象类不一定
- 一个类只能继承一个抽象类,不过可以实现多个方法
示例
一个抽象类
abstract public class Animal {
int size;
String color;
// 可以有具体的方法
public void sleep() {
System.out.println("sleep");
}
public abstract void eat();
}
一个接口
public interface Pet {
public abstact void beFriendly();
public abstract void play();
}
继承两者
public class Dog extends Animal implements Pet {
// 实现接口的两个方法
public void beFriendly(){
System.out.println("befriendly");
}
public void play(){
......
}
// override 抽象类中的方法
public void eat() {
....
}
}