抽象类定义
Java提供一种抽象方法的机制,抽象方法是不完整,只有声明而没有方法体,抽象方法用关键字abstract修饰:
abstract void function(){}
如果一个类包含一个或多个抽象方法,则这个类必须被限定为抽象类,非抽象类不能拥有抽象方法。
抽象类不能实例化,但抽象类可以有多种构造器,供其子类使用。抽象类可以定义抽象方法和非抽象方法,非抽象方法不能有抽象方法。如果子类有未覆盖的抽象方法,则该子类也是抽象类。
抽象类和抽象方法是为了设计更简洁明晰的代码。
抽象类理解
抽象的一个含义是共性,抽象类的抽象方法,将在该类的子类中具体化(覆盖),不同的子类可以进行有区别的具体化,但所有的子类都必须支持抽象方法的操作,抽象超类的抽象方法是对其子类共性的一种总结。
抽象的另一种含义是不存在,不存在单纯的抽象类对象,抽象类不可实例化,只有所有抽象方法都具体化的子类是可以实例化的。
抽象类的机制有点像柏拉图的理型论,现实中的事物可以抽象成理型,理型就像做饼干模子,面粉填进模具,烤出来就是想要形状的饼干;模子就是抽象的理型,而饼干是根据理型所具体化出的实物;然而饼干和模具之间永远是有区别的(比如缺了一块或者突出来一块),但人看到它们都知道它们是什么,或者说烤出它们的模子是什么。柏拉图称人类意识中的这个“模具”为“理型”,人识别和归纳不同的事物,是根据意识中的理型,看到马是马,是因为马符合“马的理型”,看到牛市牛,是因为牛符合“牛的理型”。然而马与马彼此间都是不一样的,高头大马是马,矮脚马也是马,汗血宝马是马,断了腿的马还是马,因为它们都符合“马的理型”,然而理型中的马实际是不存在的,因为它是一个抽象概念。(更多的相关知识可以搜索“柏拉图+理型”,我理解也不深)
这就像Java中的抽象机制,抽象类就是理型(马),不同的品种可以是子类(蒙古马,波斯马),抽象类(马)总结了子类的共性(蒙古马,波斯马),抽象类不能实例化,而具体类可以被实例化。
接口理解
接口可以定义一系列的方法,所有需要这些方法的类可以通过实现这个接口使用这些方法。Java语言具有单继承限制,一个类只能有单一父类,但可以有多个子类,这有点像遗传机制,一个人的生理父母亲都只各能有一个人。单继承带来逻辑上的清晰(一个人如果有很多生理父母亲想想就很混乱),但也存在限制,例如,一个父类的五个子类,其中三个子类有相同的方法,好比一个父亲有五个儿子,父亲不会弹琴,儿子中两个会弹琴,弹琴就是他们的相同方法,但因为单继承限制,必须要在两个子类中都要写同样弹琴方法,这样就很繁琐,因此出现了接口。接口定义了一系列方法,类通过实现接口获得这些方法,这样,上述的问题,就可以通过让会弹琴的儿子实现弹琴的接口就可以了。这样,五个儿子各有异同,老大老四会弹琴,老三老四会围棋,就可以老大继承弹琴接口,老三继承围棋接口,老四继承弹琴和围棋接口,而弹琴和围棋的方法只用写一次就够了。
可以感受到,抽象类和借口具有共性,都是为了更好的代码复用而设计的机制,都可以让普通类继承其中未具体化的方法。
有些不同的是,Interface是一种规则,而非实体,它允许创建者确定方法名,参数列表和返回类型,但没有任何方法体。它在抽象的道路上走得更远,就好像抽象类告诉你鸟会飞,而接口告诉你有一种存在叫飞翔。一个接口表示“所有实现这个接口的类看以来都像这样”。
使用接口需要用interface关键字来代替class,并使用implements关键词来实现,而抽象类使用abstract关键词加在class前,然后像普通类一样用extends来继承。抽象类是普通类和接口之间的一个中庸之道。
抽象类和接口是Java提供的两种非常有用的机制,在很多情况下,两种方法都能实现想要的功能,如何使用要看具体的情况和使用的设计模式,已达到代码复用性,逻辑性,健壮性的权衡。
抽象类和接口的区别
参数 | 抽象类 | 接口 |
---|---|---|
默认的方法实现 | 它可以有默认的方法实现 | 接口完全是抽象的。它根本不存在方法的实现 |
实现 | 子类使用extends关键字来继承抽象类。如果子类不是抽象类的话,它需要提供抽象类中所有声明的方法的实现。 | 子类使用关键字implements来实现接口。它需要提供接口中所有声明的方法的实现 |
构造器 | 抽象类可以有构造器 | 接口不能有构造器 |
与正常Java类的区别 | 除了你不能实例化抽象类之外,它和普通Java类没有任何区别 | 接口是完全不同的类型 |
访问修饰符 | 抽象方法可以有public、protected和default这些修饰符 | 接口方法默认修饰符是public。你不可以使用其它修饰符。 |
main方法 | 抽象方法可以有main方法并且我们可以运行它 | 接口没有main方法,因此我们不能运行它。 |
多继承 | 抽象方法可以继承一个类和实现多个接口 | 接口只可以继承一个或多个其它接口 |
速度 | 它比接口速度要快 | 接口是稍微有点慢的,因为它需要时间去寻找在类中实现的方法。 |
添加新方法 | 如果你往抽象类中添加新的方法,你可以给它提供默认的实现。因此你不需要改变你现在的代码。 | 如果你往接口中添加方法,那么你必须改变实现该接口的类。 |
继承与多态区别
继承,子类继承父类中所以的属性和方法,但是对于private的属相和方法,由于这个是父类的隐私,所以子类虽然是继承了,但是没有可以访问这些属性和方法的引用,所以相当于没有继承到。很多时候,可以理解为,没有继承。
多态:就是父类引用可以持有子类对象。这时候只能调用父类中的方法,而子类中特有方法是无法访问的,因为这个时候(编译时)你把他看作父类对象的原因,但是到了运行的时候,编译器就会发现这个父类引用中原来是一个子类的对像,所以如果父类和子类中有相同的方法时,调用的会是子类中的方法,而不是父类的。
可以这么说:编译时看父类,运行时看子类。
参考资料:
《Thinking in Java》
《数据结构与算法分析(Java实现)》
http://www.importnew.com/12399.html