学习笔记一:接口与继承(抽象类)

学习笔记参考来源

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("进行物理攻击");
    }
 
}

在这里,不要将重写和实现抽象方法相混淆,实现父类的抽象方法的步骤:

  1. 继承父类
  2. 重写(override)父类的抽象方法

子类重写父类抽象方法是实现父类抽象方法的最后一步,即在这里重写的目的是实现父类的抽象方法。

那么问题来了,继承了抽象类的子类需要把抽象类中的方法(包括抽象方法和普通方法)重写一遍吗?
我查了查资料,可以了解一下:
答案是(不一定)

  1. 普通类继承,并非一定要重写父类方法。
  2. 抽象类继承,如果子类也是一个抽象类,并不要求一定重写父类方法。如果子类不是抽象类,则要求子类一定要实现父类中的抽象方法。
  3. 接口类继承。如果是一个子接口,可以扩展父接口的方法;如果是一个子抽象类,可以部分或全部实现父接口的方法;如果子类不是抽象类,则要求子类一定要实现父接口中定义的所有方法。

抽象类与抽象方法

前面已经提到了,抽象类有抽象方法,也有普通方法。

那么类可不可以只有抽象方法或者只有普通方法呢?答案是可以的。
仅有抽象方法的类肯定是抽象类。
而仅有普通方法的类也可以声明为抽象类!(注意是也可以!意思是你可以把这个类声明为抽象类,也可以不声明为抽象类) 也就是说一个类可以在不提供抽象方法的前提下,声明为抽象类。

那么问题来了,既然一个类中没有抽象方法,那么为什么还要把这个类声明为抽象类呢?

因为一旦一个类被声明为抽象类,那么这个类就不能够被直接实例化!

/*
	没有抽象方法的一个抽象类
*/
public abstract class Hero {
    String name;
    float hp;
    float armor;
    int moveSpeed;
       
    public static void main(String[] args) {
        //虽然没有抽象方法,但是一旦被声明为了抽象类,就不能够直接被实例化
        Hero h= new Hero();//报错(具体如下图所示)
    }
          
}

比如我有一个类,它没有抽象方法,但是呢,我不想它可以直接实例化,这个时候就可以将这个类声明为抽象类。
学习笔记一:接口与继承(抽象类)_第1张图片 学习笔记一:接口与继承(抽象类)_第2张图片

抽象类与接口的区别

区别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接口的类,都需要做改动。
但是引入了默认方法后,原来的类,不需要做任何改动,并且还能得到这个默认方法
通过这种手段,就能够很好的扩展新的类,并且做到不影响原来的类

你可能感兴趣的:(java学习笔记)