抽象类
抽象的产生由来
- 抽象方法
- 当多个类中具有共性方法时,我们就会向上抽取形成父类,并在父类中定义这个共性方法。
- 而有时,父类中的方法并不能明确每个子类的具体实现,那么这种方法就称为抽象方法。
- 抽象方法的定义:用abstract关键字修饰,且没有方法体,直接以分号结尾的方法。
- 抽象方法必须被子类实现。
格式:
public sbstract 方法名(参数列表);
抽象类
具有抽象方法的类就是抽象类,抽象类中才可以写抽象方法。
格式:public abstrat class 类名{ }
抽象类的特点
- 抽象类必须被abstract修饰
- 不能被创建对象,(不能实例化,不能new)
- 抽象方法必须被abstract修饰,且没有方法体,直接以分号结尾的方法。
- 抽象类中可以没有抽象方法(但一般不那么做,因为这么做没有任何意义)。抽象方法必须在抽象类中。(抽象类中才可以定义抽象方法,如果你写了抽象方法,那一定要把类变成抽象类。)
- 抽象类中可以有普通方法而且非常有必要,它是可以给子类继承的,为那些具有相同功能相同实现细节的类。(抽象类中可以有普通方法,但是你不能实例化这个抽象类也就不能调用这个普通方法,还定义普通方法干什么呢?答:虽然它本身不能不能调用普通方法,但是它的子类可以继承普通方法,可以实例化调用,当一些子类中都具有和其他子类相同的功能并且实现方式也一样时,就可以把方法定义成普通方法,防止重复定义。定义抽象方法是因为具有这个功能但具体实现方式不同所以,定义普通方法是因为具有同样的功能并且细节实现也是一样。每个类中单独定义自己的方法是因为跟其他子类没有共同点,这个这个小类独有的功能。 总之同功能不同实现,抽象。同功能同实现普通)
抽象类的使用
步骤:
- 定义抽象类的子类
- 重写抽象类的所有抽象方法
- 创建子类对象,调用重写后的方法
细节
- 问:反正子类都要重新定义自己的功能,为什么还要继承具有抽象方法的抽象类?
答:因为继承了抽象类后就必须重写所有的抽象方法,这表示当前的子类是属于父类继承体系的一份子,作为该类的子类就必须具备此功能。 - 问:抽象类中不定义抽象方法的意义是什么?
答:一个类使用abstract修饰后,它就不能被实例化了,就必须通过子类的继承和重写才有意义。这是设计模式的体现。 - 问:抽象类一定是父类吗?
答:从代码角度来说不一定;从实际意义和思考角度来说,抽象类一定是一个父类。
抽象可以再抽象
比如A抽象类,B继承A。B本来是必须实现A中的方法的,但是B不想实现A中的方法,它还想再添加两个抽象方法或者不添加,让其他人去实现这个B那么可以给B加abstract。
实际开发中抽象类的使用
使用匿名内部类的方法
- 创建抽象类的子类对象,重写方法后,就可以直接调用方法
格式:new 抽象类名 / 接口名(){ // 重写所有抽象方法 };还可以在分号前调用方法
这个有点像JavaScript中的var x= function(){
//函数体
};的方式
匿名对象的创建
- 概念:创建对象时,不指定变量名
- 好处:简化代码的书写
- 弊端:匿名对象只能使用一次
格式:
new 数据类型(参数);
---接口
生活中的接口:笔记本上的USB
USB:
- 笔记本上如果要连入外设,那么这些外设必须都是以USB接口作为连入方式的
- 当笔记本上的USB接口连入了外设后,笔记本就有了额外的功能了,例如:VR,风扇,手柄
接口的好处:
- 实现额外功能的扩展
- 接口是对外暴露的规则,表示如果想要使用接口来扩展功能,那么必须符合这些规则,并且是作为同一体系下的内容
- 达到功能与具体实现的相分离(解耦)
问:接口是什么呢?
答:接口是一个比抽象类更加抽象的“抽象类”,它是功能的集合。
它使用interface关键字代替了class。
注:接口的源文件还是.java文件,并且编译后的文件还是.class文件,所以说接口是一个特殊的类
定义
格式:public interface 接口名{ }
接口中成员的特点
- 成员变量
接口中的成员变量默认被public static final
所修饰,相当于共同使用的公共工具可以用但不能修改,别人还要用呢,public是为了可以跨包的访问反正你也不能修改我是安全的,我可以随便公开。 - 成员方法
接口中的成员方法默认被public absttact
修饰,默认的就已经加上了,你加上修饰也是加,不加就是默认,已修改就错。 - 接口的使用
步骤:
- 自定义类实现(继承)接口,使用关键字implements
- 重写所有抽象方法
- 创建子类(实现类)对象,调用重写后的方法
- 接口的不同使用方式
- 类实现接口
一个类为了扩展额外的功能,而去实现接口,那么这个了类需要重写接口中的方法 - 类在继承类的时候实现接口
一个类是属于某一个继承体系的,它是某一个类的一份子,所以继承它之后具备了该类的所有属性和功能;同时还实现了功能的扩展。 - 类的多实现
一个类实现了多个接口后,需要从写这些接口的所有抽象方法,来实现功能的扩展。 - 接口继承接口,接口可以继承多个接口
接口和抽象类的异同
同:
- 都不能创建对象
- 都需要子类(实现类)重写方法后才有意义
- 都是向上抽取得到的
- 都具有抽象方法
异:
- 抽象类中可以有非抽象方法
- 接口使用的是interface和实现implements、抽象类使用的是class和继承extends
- 接口可以多继承,抽象类只能单继承。
- 继承类表示的是属于这个继承体系中的一份子,具有该类的共性内容;实现接口表示的是功能的扩展。体系模块一脉相承任何子孙都要有和功能模块不同子孙不同的功能。
问:接口和抽象类用哪个呢?
答:推荐使用接口,避免了单继承的局限性;当子类有共性方法,且这些方法的具体实现也相同时。
Java 1.8的新特性
在接口中也可以定义非抽象方法啦!!!
格式:
default 返回类型 方法名(){
}
总结
- 接口中没有普通方法,只有抽象方法。接口中的所有成员都是默认 公开 静态 最终。但是目前Java1.8新增了default修饰的方法,就是普通方法,这个普通方法就是个普通方法,和抽象类中的普通方法类似。
- 抽象类可以重写普通方法,可以继承普通方法。但是无论是对于抽象方法还是普通方法,无论是继承还是接口实现都要遵守子类中的方法作用权限要大于等于父类。
- 接口可以继承接口可以多继承接口,但是接口不能实现接口。即接口不能impelements接口。
- 接口不可以循环闭环继承
- 接口中default的普通方法依然是public类型。这个default在接口中是指普通方法的关键字不是指访问权限。
- 抽象类的子类和子类对象可以更改和调用抽象类中的变量。
- 接口是抽象中的抽象,终极抽象。抽象类中还存在相同实现的方法,而在接口中还会再向上抽象直到不存在相同的实现方法只存在相同的功能。但是这个设定再1.8被打破存在default。
例如:
狗和猫可以抽象为动物,虽然吃的不一样可以定义为抽象方法,但睡觉一样可以定义为具体方法。再把动物和人类进行抽象,这时候不但连吃不一样,连睡觉都不一样,这时候接口叫生物,吃和睡都是抽象方法。所以生物是抽象类。现在抽象类中可以有具体方法并且可以多继承多实现,渐渐的抽象类没有了市场。
额外
- 一个
.java
文件中可以写两个类,但是编译的时候还是会把文件中的每一个类单独编译成一个.class
文件中,一个类一个.class
。一个接口也会独占一个.class文件。 - 抽象方法必须被实现,具体方法会自动被继承。
- 静态变量是在类加载的收就加载了,它是类级别的,所以是所有对象的共享数据。
- 在一个类中可以出现重载,但是重载只关乎参数名和参数列表和返回类型无任何关系,所以以返回类型来作为重载的是错误。即,方法名相同,参数列表相同,但返回类型不同的方法直接报错。
所以当一个类要实现两个接口时这两个接口有的方法名相同但参数列表不同可以作为重载,但是只是返回类型不同会报错崩溃。因此接口的实现以及多接口的实现可以接受重载和重载的规则一样,但不接受无理取闹。仅是返回类型不同绝对不允。