1. 程式人生 > >抽象類、內部抽象類、模板設計演算法

抽象類、內部抽象類、模板設計演算法

抽象類的定義與使用
定義: 抽象類只是在普通類的基礎上擴充了一些抽象方法而已。
抽象方法:

  • 只宣告未定義的方法(沒有方法體)
  • 所有抽象方法要求使用abstract來定義,並且抽象方法所在類必須用abstract來定義,表示抽象類。

抽象類的使用原則:

  • 所有抽象類必須有子類(abstract與final不能同時使用,是因為final宣告的類不能有子類);
  • 抽象類的子類必須覆寫抽象類的所有抽象方法,前提是這個子類不在是一個抽象類,如果是子類是一個抽象類,可以不全覆寫父類抽象方法(abstract與private不能同時使用);
  • 如果抽象類需要例項化物件,必須通過子類向上轉型為其例項化(抽象類無法建立例項化物件)
abstract class Person   //抽象類
{
    private String name;
    abstract public void fun1(); //抽象方法
    //abstract public void func2();  //兩個抽象方法必須全覆寫
}
class Student extends Person
{
    public void fun1()  //重寫抽象方法
    {
        System.out.println("子類繼承抽象類");
    }
}
public class  Abstract
{
    public static void main(String[] args)
    {
        Person p=new Student(); //向上轉型
        p.fun1();  //呼叫的子類中被覆寫的fun1();
    }
}

抽象類的相關規定
1.抽象類允許提供構造方法,並且子類也遵循物件例項化流程,先呼叫父類構造方法而後呼叫子類構造方法。
物件例項化操作包括:

  • 進行類載入
  • 進行類物件的空間開闢
  • 進行類物件的屬性初始化(構造方法)
/////面試題
abstract class Person   //抽象類
{
    public Person() //3.呼叫父類構造
    {
        this.fun1(); //4.呼叫fun1,發現父類中fun1為抽象類,就調子類中覆寫的fun1
    }
    abstract public void fun1(); //抽象方法
   
}
class Student extends Person
{
    private int num=100; //7.調子類構造時初始化屬性變為100
    public Student(int num)  //2.呼叫子類構造
    {
        this.num=num; //賦值後num變為30
    }
    public void fun1() //5.此時還沒有調子類構造,屬性是在調建構函式時初始化,所以此時還沒有初始化屬性
    {
        System.out.println(this.num); // 6.沒有初始化,屬性預設值為0
    }
}
public class  Abstract
{
    public static void main(String[] args)
    {
        new Student(30);//1.例項化子類物件  結果為0
        new Student(30).fun1();  //結果為0 30 ,因為先調了父類構造,所以有0
    }
}

2.抽象類中允許不定義任何的抽象方法,但是此時抽象類依然無法直接建立例項化物件。

**圖片**

3.abstract不能與final一起使用:abstract定義類必須有子類,final定義類不能有子類;
abstract不能與private一起使用:abstract定義方法必須被重寫,private定義方法在子類不可見。

內部抽象類
子類可以只覆寫父類的直接抽象方法,不管父類內部類抽象方法;如果需要重寫父類內部類抽象方法,可以在子類中定義一個父類內部抽象類的子類來重寫:

abstract class Person
{
    public abstract void fun1();
    abstract class  B
    {
        public abstract void fun2();
    }
}
class Student extends Person
{
    public void fun1()  //對父類直接抽象方法覆寫
    {
    }
    class C extends B //重新定義一個子類
    {
        public void fun2()
        {          
        }
    }
}

模板設計演算法
模板設計演算法基於抽象類,核心是封裝演算法。模板方法定義了一個演算法的步驟,並允許子類為一個或多個步驟提供具體實現。

模板(模板方法)模式:
在一個方法中定義一個演算法的骨架,並將一些具體步驟延遲到子類實現。模板模式使得子類可以在不改變演算法結構的基礎上,重新定義演算法中的某些步驟。
如下列的咖啡因飲料:咖啡和茶都有相同的步驟:煮沸水、泡咖啡或者浸泡茶、向咖啡或茶新增東西、將飲料倒入杯中,這四個步驟咖啡和茶都有,即是相同的演算法結構,那麼就可以把這四個步驟定義在一個演算法模板中,不同的步驟子類重寫:

import java.util.Scanner;

abstract class CaffeineBerverage  //父類是咖啡因飲料
{
    //模板方法 宣告為final:只允許子類使用,不允許覆寫
    final void prepareRecipe()
    {
        boilWater();
        brew();
        if(customerWantsCondiments())
        {
             addCondiments();
        }
        pourInCup();
    }
    public void boilWater()  //燒水
    {
        System.out.println("將水煮沸");
    }
    public void pourInCup()  
    {
        System.out.println("將飲料調入杯中");
    }
    ////鉤子方法:子類選擇性覆蓋 
    boolean customerWantsCondiments() //顧客是否想要新增東西,因為有的顧客不想新增東西
    {
        return true;
    }
    abstract public void brew();//處理飲料的方式
    abstract public void addCondiments(); //向飲料里加東西
}
class Coffee extends CaffeineBerverage  //咖啡
{
    public void  brew()
    {
        System.out.println("沖泡咖啡");
    }
    public void addCondiments()
    {
        System.out.println("加糖和奶");
    }
    boolean customerWantsCondiments()  //重寫
    {
        System.out.println("請問您想要加糖或奶嗎? y/n");
        String result=getUserInfo();
        if(result.equals("y"))
        {
            return true;
        }
        else
        {
            return false;
        }

    }
    private String getUserInfo()
    {
        Scanner scanner=new Scanner(System.in);
        String str=scanner.nextLine();
        return str;
    }
}

class Tea extends CaffeineBerverage
{
    public void brew()
    {
        System.out.println("浸泡茶葉");
    }
    public void addCondiments()
    {
        System.out.println("加檸檬");
    }
}

public class Abstract
{
    public static void main(String[] args)
    {
        CaffeineBerverage coffee=new Coffee();
        coffee.prepareRecipe();
        CaffeineBerverage tea=new Tea();
        tea.prepareRecipe();
    }
}

在這裡插入圖片描述