学习笔记参考来源
java学习路线…推荐链接:java-接口与继承-抽象类
学习笔记难免出错 望多指正!!!
什么叫做抽象类呢?
如果一个类中声明了一个方法,但这个方法没有实现体,也就说这是一个空方法,而这样的方法就叫做抽象方法,它必须使用“abstract”修饰符!
当一个类含有抽象方法的时候,这个类必须被“abstract”修饰符声明为抽象类!
抽象类是比普通类更具有通用性的,什么意思呢?
在java所有类中,Object是通用性最广泛的一个类,人们将它作为派生其他类的基类,而不是作为特定的实例类。
例子:
为英雄类Hero增加一个抽象方法attack(攻击),并且把Hero声明为abstract。
有:法术英雄类APHero,物理英雄类ADHero,可物可法英雄类ADAPHero三个类; 都是Hero的子类,继承了Hero的属性和方法。不过这三个类的attack攻击方法肯定是不一样的,实现如下:
Hero.java
/*
Hero类是三个类的父类
*/
//包省略
public abstract class Hero{//因为Hero类含有抽象方法,所以必须加上abstract为抽象类
String name;
float hp;
float armor;
int moveSpeed;
public static void main(String[] args) {
}
// 抽象方法attack
// Hero的子类会被要求实现attack方法
public abstract void attack();
//空方法体
}
ADHero.java
/*
物理英雄类
*/
public class ADHero extends Hero{
public void physicAttack() {
System.out.println("进行物理攻击");
}
@Override
public void attack() {
physicAttack();
}
}
APHero.java
/*
法术英雄类
*/
public class APHero extends Hero{
@Override
public void magicAttack() {
System.out.println("进行魔法攻击");
}
@Override
public void attack() {
magicAttack();
}
}
ADAPHero.java
/*
可物可法英雄类
*/
public class ADAPHero extends Hero{
@Override
public void attack() {
System.out.println("既可以进行物理攻击,也可以进行魔法攻击");
}
public void magicAttack() {
System.out.println("进行魔法攻击");
}
public void physicAttack() {
System.out.println("进行物理攻击");
}
}
在这里,不要将重写和实现抽象方法相混淆,实现父类的抽象方法的步骤:
- 继承父类
- 重写(override)父类的抽象方法
子类重写父类抽象方法是实现父类抽象方法的最后一步,即在这里重写的目的是实现父类的抽象方法。
那么问题来了,继承了抽象类的子类需要把抽象类中的方法(包括抽象方法和普通方法)重写一遍吗?
我查了查资料,可以了解一下:
答案是(不一定)
- 普通类继承,并非一定要重写父类方法。
- 抽象类继承,如果子类也是一个抽象类,并不要求一定重写父类方法。如果子类不是抽象类,则要求子类一定要实现父类中的抽象方法。
- 接口类继承。如果是一个子接口,可以扩展父接口的方法;如果是一个子抽象类,可以部分或全部实现父接口的方法;如果子类不是抽象类,则要求子类一定要实现父接口中定义的所有方法。
抽象类与抽象方法
前面已经提到了,抽象类有抽象方法,也有普通方法。
那么类可不可以只有抽象方法或者只有普通方法呢?答案是可以的。
仅有抽象方法的类肯定是抽象类。
而仅有普通方法的类也可以声明为抽象类!(注意是也可以!意思是你可以把这个类声明为抽象类,也可以不声明为抽象类) 也就是说一个类可以在不提供抽象方法的前提下,声明为抽象类。
那么问题来了,既然一个类中没有抽象方法,那么为什么还要把这个类声明为抽象类呢?
因为一旦一个类被声明为抽象类,那么这个类就不能够被直接实例化!
/*
没有抽象方法的一个抽象类
*/
public abstract class Hero {
String name;
float hp;
float armor;
int moveSpeed;
public static void main(String[] args) {
//虽然没有抽象方法,但是一旦被声明为了抽象类,就不能够直接被实例化
Hero h= new Hero();//报错(具体如下图所示)
}
}
比如我有一个类,它没有抽象方法,但是呢,我不想它可以直接实例化,这个时候就可以将这个类声明为抽象类。
抽象类与接口的区别
区别1:
子类只能继承一个抽象类,不能继承多个
子类可以实现多个接口
区别2:
抽象类可以定义
public,protected,package,private
静态和非静态属性
final和非final属性
但是接口中声明的属性,只能是
public
静态
final的
即便在这个接口中没有显式的声明
public interface AP {
public static final int resistPhysic = 100;//物抗
//resistMagic即便没有显式的声明为 public static final
//但依然默认为public static final
int resistMagic = 0;//法抗
public void magicAttack();//法术攻击
}
注:默认方法
抽象类的实体方法就是普通方法。而接口中的实体方法,叫做默认方法
默认方法是JDK8新特性,指的是接口也可以提供具体方法了,而不像以前,只能提供抽象方法
Mortal 这个接口,增加了一个默认方法 revive,这个方法有实现体,并且被声明为了default
public interface Mortal {
public void die();//英雄死亡
default public void revive() {
System.out.println("本英雄复活了");
}
}
为什么会有默认方法?
假设没有默认方法这种机制,那么如果要为Mortal增加一个新的方法revive,那么所有实现了Mortal接口的类,都需要做改动。
但是引入了默认方法后,原来的类,不需要做任何改动,并且还能得到这个默认方法
通过这种手段,就能够很好的扩展新的类,并且做到不影响原来的类