隨着繼承層次中一個個新子類的定義,類變得越來越具體,而父類別則更一般,更通用。類的設計應該保證父類別和子類能夠共用特徵。有時將一個父類別設計得非常抽象,以至於它沒有具體的範例,這樣的類叫做抽象類
。
抽象類的出現使物件導向更加規範,比如人是一個抽象的概念,沒有具體的物件,我們應該將其抽象成一個類,它無法生成物件範例,卻擁有一些人通用的屬性和方法。有些方法人類都是一樣的行爲,比如說都是用嘴吃飯,用耳朵聽聲音等;但有些則不是,比如工作,不同的崗位人們有不同的工作行爲,那麼這些行爲的具體實現在子類完成,Person父類別只負責定義。
package Random_name.sgm.abstract_interface;
/**
* @Program: JavaSE
* @ClassName: TestMain
* @Author: Mr.BitHachi
* @CreateTime: 2020-08-08 12:07
* @Version: V1.0
* @Description:
**/
abstract class A {
private int aa=10;
static final String str="可以有static屬性";
static{
System.out.println("可以有程式碼塊");
}
A(int aa){
this.aa=aa;
}
public abstract void m1();
public void m2() {
System.out.println("A類中定義的m2方法");
System.out.println("A類中的屬性a="+this.aa);
}
}
class B extends A {
private int bb=10;
B(int aa,int bb){
super(aa);
this.bb=20;
}
public void m1() {
System.out.println("B類中定義的m1方法");
}
public void m2() {
System.out.println("B類中重寫的的m2方法");
}
void m3(){
super.m2();
}
}
class Test {
public static void main(String args[]) {
A a = new B(20,20);
a.m1();
a.m2();
B b=new B(30,30);
b.m3();
}
}
執行結果:
可以有程式碼塊
B類中定義的m1方法
B類中重寫的的m2方法
A類中定義的m2方法
A類中的屬性a=30
抽象類的應用與多型應用相關聯。
抽象類體現的是一種模板模式的設計,抽象類作爲多個子類的通用模板,子類在抽象類的基礎上進行擴充套件、改造,但子類總體上會保留抽象類的行爲方式。
抽象類解決的問題:
模板模式
。模板方法設計模式是程式設計中經常用得到的模式。各個框架、類庫中都有他的影子,比如常見的有:
介面中沒有構造器
。介面中不能擁有程式碼塊
public static final
修飾的。public abstract
修飾的。extends
SuperClass implements
InterfaceA{ }介面的定義舉例:
JDK8中關於介面的改進:
Java 8中,你可以爲介面新增靜態方法和預設方法。從技術角度來說,這是完全合法的,只是它看起來違反了介面作爲一個抽象定義的理念。
靜態方法
:使用 static 關鍵字修飾。可以通過介面直接呼叫靜態方法,並執行其方法體。我們經常在相互一起使用的類中使用靜態方法。可以在標準庫中找到像Collection/Collections或者Path/Paths這樣成對的介面和類。
預設方法
:預設方法使用 default 關鍵字修飾。可以通過實現類物件來呼叫。我們在已有的介面中提供新方法的同時,還保持了與舊版本程式碼的相容性。比如:java 8 API中對Collection、List、Comparator等介面提供了豐富的預設方法。
解決辦法
:實現類必須覆蓋介面中同名同參數的方法,來解決衝突。類優先原則
。介面中具有相同名稱和參數的預設方法會被忽略。介面中靜態方法和預設方法必須給出方法體,不能只定義
根據介面的特點,綜合舉例:
/************ 一個類可以實現多個無關的介面 ************/
interface Runner {
int a=10;
public void run();//jdk8之前只能宣告非static和defult的方法
static void fun2() {//jdk8之後可以定義static和defult的方法,不能宣告,必須給出方法體
System.out.println("interface Runner static fun2");
}
default void fun3(){
System.out.println(this.a);//可以使用this,但是不能更改其值,因爲預設預設public static final
System.out.println("interface Runner default fun3");
}
}
interface Swimmer {
public double swim();
default void fun3(){
System.out.println("interface Swimmer default fun3");
}
default void skip(){
System.out.println("interface Swimmer default skip");
}
}
class Creator{
public void eat() {
System.out.println("eat");
}
public void skip(){
System.out.println("class Creator skip");
}
}
class Man extends Creator implements Runner ,Swimmer{
public void run() {
System.out.println("run");
}
public double swim() {
System.out.println("swim");
return 1.1d;
}
public void fun3(){
System.out.println("class Man fun3");//類覆蓋兩個介面中預設的方法fun3()
Runner.super.fun3();//呼叫原介面中預設的方法
Swimmer.super.fun3();
}
}
class Test{
public static void main(String args[]){
Test t = new Test();
Man m = new Man();
t.m1(m);//介面多型參照,與繼承關係類似,介面與實現類之間存在多型性
t.m2(m);
t.m3(m);
System.out.println("-----------");
Runner.fun2();
System.out.println("-----------");
System.out.println(Runner.a);
System.out.println("-----------");
m.fun3();
System.out.println("-----------");
m.skip();
}
public void m1(Runner f) {//介面多型參照
f.run();
}
public void m2(Swimmer s) {//介面多型參照
s.swim();
}
public void m3(Creator a) {//介面多型參照
a.eat();
}
}
執行結果:
run
swim
eat
-----------
interface Runner static fun2
-----------
10
-----------
class Man fun3
10
interface Runner default fun3
interface Swimmer default fun3
-----------
class Creator skip
題一:
interface A {
int x = 0;
}
class B {
int x = 1;
}
class C extends B implements A {
public void pX() {
System.out.println(x);//Error
System.out.println(super.x);//1
System.out.println(A.x);//0
}
public static void main(String[] args) {
new C().pX();
}
}