在面向对象的领域,一切皆为对象,所有的对象都是用类来描述的。
抽象类
如果我们要定义一个类,这个类并没有完整的描述某个对象或者没有更加具体的描述某个对象,因此需要更加具体的类来描述这个对象的时候,这个我们要定义的类,就叫做抽象类。抽象类用关键字abstract来描述,抽象类和普通类最大的区别在于:抽象类不能被实例化,也就是说,对于Person这个抽象类,我们在别的类中并不能使用new Person()来获得它的引用。
abstract不仅可以定义抽象类,也可以定义抽象方法。抽象方法是一种从很多类中抽象出来的一类被共同需要的方法,它具有的是共性,而具体在各个类中如何被实现,是不可知的。如果一个类中有抽象方法,那么这个类必须是抽象类。反过来讲,抽象类中可以没有抽象方法,但抽象方法必须被定义在抽象类中。但是一般而言,我们之所以定义抽象类,是因为要在其中定义抽象方法,所以一般情况下,抽象类中都是具有抽象方法的。
抽象类只能被继承,并且抽象类不支持多继承。一个类只能继承一个抽象类。继承的关键字是extends,如果一个类继承了某个抽象类,那么它必须实现该抽象类中所有的抽象方法,否则只能也抽象化。举个例子,一个离婚女人带着三个孩子生活,如果你娶了这个女人,那么你必须连带着照顾她的三个孩子。大概就是这么个意思。
抽象方法是没有大括号的,仅仅在括号后面加个分号。public abstract void sleep();
接口
接口是一种规范。
这是一句废话,但也是一句真话。接口是一组抽象方法的集合,接口中定义的方法没有方法体,只有方法名,以分号结束。
我们为什么要用到接口呢?
1.我们在开发过程中,经常遇到这种情况:多个类中共同使用一个或者数个相同的方法名。这些方法中进行的行为都是一样的,但是具体的逻辑操作是不一样的。如果我们新建一个类就要重新建一个方法,那么效率会非常低,而且不利于代码的扩展。
接口和抽象类一样,也不能被实例化,但可以被实现。如果一个类实现了某个接口,那么它必须实现该接口中描述的所有方法,除非它被声明为抽象类。接口使用关键字interface来定义。
接口中的方法都是可以被外部访问的,所以接口的方法可以不需要public 来修饰。
接口中也可以声明变量,一般是final 或者static类型的,要以常量来初始化,实现接口的类不能改变接口中的变量。
接口访问权限有两种:public权限和默认权限,如果接口的访问权限是public的话,那么所有的变量和方法都是public。而默认权限只有同一个包下的类才能进行访问。
一个接口可以继承另一个接口,关键字也是extends,另外,接口支持多继承,一个类可以同时实现多个接口。
抽象类和接口的相同点和不同点
相同点:1.都不能被实例化 2.都包含抽象方法,这些抽象方法描述了系统能提供哪些服务,而这些服务是由继承或者实现它们的子类来实现的。
3.从系统设计的角度来说,两者都代表系统的抽象层,所以在我们实例化某个类的时候,建议将引用变量的类型声明为上层抽象类型,
这样可以提高两个系统之间的松耦合。
不同点:
1.在抽象类中可以为一些方法提供默认的实现,避免在子类中进行重复的实现,而接口中只允许抽象方法和被final或者static声明的变量
存在。另外,抽象类不支持多继承,但是接口支持多继承。一个类只能继承一个抽象类,但是可以同时实现多个接口。
2.接口从本质上来说,是接口定义者和接口实现者之间的一种规范,更类似于约定成俗。而子类和抽象类之间的关系,一般是is-a的
关系。
上面说到了松耦合,那么再说一点,就是接口可以降低项目的耦合性。
什么是降低耦合?删除调用层而不影响接受层,就是降低耦合。
这是利用面向对象三大特性之一:多态 完成的。多态简单的说,就是父类或者接口的引用可以接受子类的对象。
比如:
interface Person{}
public class Man implements Person{}
public class WoMan implements Person{}
Man 和 WoMan 两个类都继承了接口Person;接口的引用可以接受子类的对象,就是说:
假如现在有个方法:
public void eat(Person person){ Toast.MakeText(context, "一支穿云箭,千军万马来相见!", Toast.LENGTH_SHORT).show;}
eat(Person person)这个方法接受一个Person类型的对象,我们就可以这样:
Man man = new Man();
WoMan woMan = new WoMan();
eat(man) 或者 eat(woMan)两者都可以调用eat方法,如果哪一天把Man 和 WoMan这两个类删除了,只要接口还在,eat方法就不会受到影响,即使再新建一个别的类,但是只要这个类是实现了Person接口的,那么它就可以调用eat方法,这种随意扩展一个新的类实现原接口的方式,就叫做向后兼容!这是完美的模式!