在看Java基础的时候,经常会遇到关于接口和抽象类的相关描述与问题,然后我在百度上搜了很多相关答案,都很凌乱,都直接介绍2者的区别,没有介绍2着的原因,且很多资料一模一样;如果长时间没有接触基础知识,看起来很难理解;今天兴起,写写两者的区别吧
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
1.抽象类
1.1.抽象类的产生
当编写一个类时,我们往往会为该类定义一些方法,这些方法是用来描述该类的行为方式,那么这些方法都有具体的方法体。但是有的时候,某个父类只是知道子类应该包含怎么样的方法,但是无法准确知道子类如何实现这些方法。比如一个图形类应该有一个求周长的方法,但是不同的图形求周长的算法不一样。那该怎么办呢?
分析事物时,发现了共性内容,就出现向上抽取。会有这样一种特殊情况,就是功能声明相同,但功能主体不同。那么这时也可以抽取,但只抽取方法声明,不抽取方法主体。那么此方法就是一个抽象方法。
描述狗:行为:吼叫。
描述狼:行为:吼叫。
狗和狼之间有共性,可以进行向上抽取。抽取它们的所属共性类型:犬科。由于狗和狼都具有吼叫功能,但是他们具体怎么吼叫却不一样。这时在描述犬科时,发现了有些功能(吼叫)不具体,这些不具体的功能,需要在类中标识出来,通过java中的关键字abstract(抽象)。
当定义了抽象函数的类也必须被abstract关键字修饰,被abstract关键字修饰的类是抽象类。
1 abstract class 犬科 2 { 3 abstract void 吼叫();//抽象函数。需要abstract修饰,并分号;结束 4 } 5 class Dog extends 犬科 6 { 7 void 吼叫() 8 { 9 System.out.println("汪汪汪汪"); 10 } 11 } 12 class Wolf extends 犬科 13 { 14 void 吼叫() 15 { 16 System.out.println("嗷嗷嗷嗷"); 17 } 18 }
1.2.抽象类的特点
1、抽象类和抽象方法都需要被abstract修饰。抽象方法一定要定义在抽象类中。
2、抽象类不可以创建实例,原因:调用抽象方法没有意义。
3、只有覆盖了抽象类中所有的抽象方法后,其子类才可以实例化。否则该子类还是一个抽象类。
之所以继承,更多的是在思想,是面对共性类型操作会更简单。
1.3.抽象类的细节问题
1、抽象类一定是个父类?
是的,因为不断抽取而来的。
2、抽象类是否有构造函数?
有,虽然不能给自己的对象初始化,但是可以给自己的子类对象初始化。
抽象类和一般类的异同点:
相同:
1、它们都是用来描述事物的。
2、它们之中都可以定义属性和行为。
不同:
1、一般类可以具体的描述事物。抽象类描述事物的信息不具体
2、抽象类中可以多定义一个成员:抽象函数。
3、一般类可以创建对象,而抽象类不能创建对象。
3、抽象类中是否可以不定义抽象方法。
是可以的,那这个抽象类的存在到底有什么意义呢?仅仅是不让该类创建对象。
4、抽象关键字abstract不可以和哪些关键字共存?
- final:fianl修饰的类是无法被继承的,而abstract修饰的类一定要有子类。 final修饰的方法无法被覆盖,但是abstract修饰的方法必须要被子类去实现的。
- static:静态修饰的方法属于类的,它存在与静态区中,和对象就没关系了。而抽象方法没有方法体,使用类名调用它没有任何意义。
- private:私有的方法子类是无法继承到的,也不存在覆盖,而abstract和private一起使用修饰方法,abstract既要子类去实现这个方法,而private修饰子类根本无法得到父类这个方法。互相矛盾。
2.接口
2.1.接口的定义与实现
当一个抽象类中的所有方法都是抽象方法时,那么这个抽象类就可以使用另外一种接口这种机制来体现。
接口怎么定义呢?定义普通的类或者抽象类可以使用class关键字,定义接口必须interface关键字完成。
interface class Demo { abstract void show1(); abstract void show2(); }
接口中成员的特点:
1、接口中可以定义变量,但是变量必须有固定的修饰符修饰,public static final 所以接口中的变量也称之为常量。
2、接口中可以定义方法,方法也有固定的修饰符,public abstract
3、接口中的成员都是公共的。
4、接口不可以创建对象。
5、子类必须覆盖掉接口中所有的抽象方法后,子类才可以实例化。否则子类是一个抽象类。
interface Demo//定义一个名称为Demo的接口。 { public static final int NUM = 3; public abstract void show1(); public abstract void show2(); } //定义子类去覆盖接口中的方法。子类必须和接口产生关系,类与类的关系是继承,类与接口之间的关系是 实现。通过 关键字 implements class DemoImpl implements Demo//子类实现Demo接口。 { //重写接口中的方法。 public void show1(){} public void show2(){} }
2.2.接口的多实现
了解了接口的特点后,那么想想为什么要定义接口,使用抽象类描述也没有问题,接口到底有啥用呢?
接口最重要的体现:解决多继承的弊端。将多继承这种机制在java中通过多实现完成了。
interface A { void show1(); } interface B { void show2(); } class C implements A,B// 多实现。同时实现多个接口。 { public void show1(){} public void show2(){} }
怎么解决多继承的弊端呢?()
弊端:多继承时,当多个父类中有相同功能时,子类调用会产生不确定性。
其实核心原因就是在于多继承父类中功能有主体,而导致调用运行时,不确定运行哪个主体内容。
为什么多实现就解决了呢?
因为接口中的功能都没有方法体,由子类来明确。
2.3.类继承类同时实现接口
接口和类之间可以通过实现产生关系,同时也学习了类与类之间可以通过继承产生关系。当在描述事物时,如果这个事物已经是整个事物体系中的一种,它又需要扩展额外的功能,这时接口就派上用场了。
子类通过继承父类扩展功能,通过继承扩展的功能都是子类应该具备的基础功能。如果子类想要继续扩展其他类中的功能呢?这时通过实现接口来完成。
class Fu { public void show(){} } interface Inter { pulbic void show1(); } class Zi extends Fu implements Inter { public void show1() { } }
接口的出现避免了单继承的局限性。父类中定义的事物的基本功能。接口中定义的事物的扩展功能。
2.4.接口的多继承
学习类的时候,知道类与类之间可以通过继承产生关系,接口和类之间可以通过实现产生关系,那么接口与接口之间会有什么关系。
多个接口之间可以使用extends进行继承。
interface A{ void show(); } interface B{ void show1(); } interface C{ void show2(); } interface D extends A,B,C{ void show3(); }
在开发中如果多个接口中存在相同方法,这时若有个类实现了这些接口,那么就要实现接口中的方法,由于接口中的方法是抽象方法,子类实现后也不会发生调用的不确定性。
2.5.接口的思想
举例:我们都知道电脑上留有很多个插口,而这些插口可以插入相应的设备,这些设备为什么能插在上面呢?主要原因是这些设备在生产的时候符合了这个插口的使用规则,否则将无法插入接口中,更无法使用。发现这个插口的出现让我们使用更多的设备。
总结:接口在开发中的它好处
1、接口的出现扩展了功能。
2、接口其实就是暴漏出来的规则。
3、接口的出现降低了耦合性,即设备与设备之间实现了解耦。
接口的出现方便后期使用和维护,一方是在使用接口(如电脑),一方在实现接口(插在插口上的设备)。例如:笔记本使用这个规则(接口),电脑外围设备实现这个规则(接口)。
3.接口和抽象类的区别
明白了接口思想和接口的用法后,接口和抽象类的区别是什么呢?接口在生活体现也基本掌握,那在程序中接口是如何体现的呢?
通过实例进行分析和代码演示抽象类和接口的用法。
1、举例:
犬:
行为:
吼叫;
吃饭;
缉毒犬:
行为:
吼叫;
吃饭;
缉毒;
2、思考:
由于犬分为很多种类,他们吼叫和吃饭的方式不一样,在描述的时候不能具体化,也就是吼叫和吃饭的行为不能明确,描述行为时,行为的具体动作不能明确,可以将这个行为写为抽象行为,那么这个类也就是抽象类。可是当犬有其他额外功能时,而这个功能并不在这个事物的体系中。这时可以让犬具备犬科自身特点的同时也有其他额外功能,可以将这个额外功能定义接口中。
interface 缉毒{ void 缉毒(); } //定义犬科的这个提取的共性功能 abstract class 犬科{ abstract void 吃饭(); abstract void 吼叫(); } // 缉毒犬属于犬科一种,让其继承犬科,获取的犬科的特性, //由于缉毒犬具有缉毒功能,那么它只要实现缉毒接口即可,这样即保证缉毒犬具备犬科的特性,也拥有了缉毒的功能 class 缉毒犬 extends 犬科 implements 缉毒{ public void 缉毒() { } void 吃饭() { } void 吼叫() { } } class 缉毒猪 implements 缉毒{ public void 缉毒() { } }
3、通过上面的例子总结接口和抽象类的区别:★★★★★
相同点:
都位于继承的顶端,用于被其他实现或继承;
都不能实例化;
都包含抽象方法,其子类都必须覆写这些抽象方法;
区别:
抽象类为部分方法提供实现,避免子类重复实现这些方法,提供代码重用性;接口只能包含抽象方法;
一个类只能继承一个直接父类(可能是抽象类),却可以实现多个接口;(接口弥补了Java的单继承)
二者的选用:
优先选用接口,尽量少用抽象类;
既要定义子类的行为,又要为子类提供共性功能时才选用抽象类;