1. 程式人生 > 其它 >什麼是介面和抽象類?

什麼是介面和抽象類?

謹記:設計嚴謹的軟體重要的標準就是需要經的起測試,一個程式好不好被測試,測試發現問題能不能被良好的修復,程式狀況能否被監控,這都有賴於對抽象類和介面的正確使用。

介面和抽象類,是高階面向物件設計的起點。想要學習設計模式,必須有著對抽象類和介面的良好認知,和SOLID的認知,並在日常工作中正確的使用他們。

先簡述一下SOLID的特指的五種原則,優秀的設計模式,都是參考於這五種原則的實現;

SOLID:

SRP:Single Responsibility Principle 單一職責原則

OCP:Open Closed Principle 開閉原則

LSP:Liskov Substitution Principle 里氏替換原則

ISP:Interface Segregation Principle 介面隔離原則

DIP:Dependency Inversion Principle 依賴反轉原則

什麼是介面和抽象類:

  • 介面和抽象類都是 “軟體工程產物”
  • 具體類——抽象類——介面:越來越抽象,內部實現的東西越來越少
  • 抽象類是未完全實現邏輯的類(可以有欄位和非public成員,他們代表了 “具體邏輯”)
  • 抽象類為複用而生:專門作為基類來使用,也具有解耦的功能。
  • 抽象類封裝的是確定的開放的是不確定的,推遲到合適的子類中去實現。
  • 介面是完全未實現邏輯的 “類”,(“純虛類”;只有函式成員;成員預設為public且不能為private) 但在新的C#版本中,介面也能擁有屬性,索引,事件,和方法的預設實現。
  • 介面為解耦而生:“高內聚,底耦合”,方便單元測試。
  • 介面是一個 “協約”,它規定你必須有什麼。
  • 它們都不能例項化,只能用來宣告變數,引用具體類的例項。

為做基類而生的 “抽象類”與 “開放/關閉原則”: (所有的規則都是為了更好的協作)

我們應該封裝那些不變的,穩定的,確定的而把那些不確定的,有可能改變的成員宣告為抽象成員,並且留給子類去實現。

錯誤的功能封裝實現:違反了開閉原則,每當新增功能就會新增程式碼

    class Program
    {
        static void Main(string[] args)
        {
            Vehicle vehicle 
= new Car(); vehicle.Run("car"); } } class Vehicle { public void Stop() { Console.WriteLine("stopped!"); } public void Fill() { Console.WriteLine("Pay and fill..."); } public void Run(string type) { //這時候又來一輛車 我們又得加程式碼了 破壞了 開閉原則 switch (type) { case "car": Console.WriteLine("car is running..."); break; case "truck": Console.WriteLine("truck is running..."); break; default: break; } } } class Car : Vehicle { public void Run() { Console.WriteLine("car is running..."); } } class Truck : Vehicle { public void Run() { Console.WriteLine("truck is running..."); } }
View Code

利用多型的機制優化上述程式碼:

class Program
{
    static void Main(string[] args)
    {
        Vehicle vehicle = new Car();
        vehicle.Run();
    }
}

class Vehicle
{
    public void Stop()
    {
        Console.WriteLine("stopped!");
    }

    public void Fill()
    {
        Console.WriteLine("Pay and fill...");
    }

    public virtual void Run()
    {
        Console.WriteLine("vehicle is running...");
    }

}

class Car : Vehicle
{
    public override void Run()
    {
        Console.WriteLine("car is running...");
    }
}

class Truck : Vehicle
{
    public override void Run()
    {
        Console.WriteLine("truck is running...");
    }
}
多型優化

我們可以發現vehicle的Run方法,我們基本上很少能用到,那我們去掉它的方法實現,一個虛方法卻沒有函式實現,這不就是純虛方法了嗎? 在C#中,純虛方法的替代型別是abstract。

在現在這個方法中,它封裝了確定的方法,開放了不確定的方法,符合了抽象類的設計,也遵循了開閉/原則。

class Program
{
    static void Main(string[] args)
    {
        Vehicle vehicle = new Car();
        vehicle.Run();
    }
}

//封裝出了確定的方法 開放了不確定的方法
abstract class Vehicle
{
    public void Stop()
    {
        Console.WriteLine("stopped!");
    }

    public void Fill()
    {
        Console.WriteLine("Pay and fill...");
    }

    public abstract void Run();
}

class Car : Vehicle
{
    public override void Run()
    {
        Console.WriteLine("car is running...");
    }
}

class Truck : Vehicle
{
    public override void Run()
    {
        Console.WriteLine("truck is running...");
    }
}
抽象類優化

這個時候我們如果想要新增一個型別的汽車,只需要繼承並實現它的抽象方法即可,這更符合開閉/原則。

現在我們讓VehicleBase做為純抽象類,這在C#中是一種常見的模式,我們可以分“代”的來完成開放的不確定方法,讓方法慢慢變得清晰和確定。

class Program
{
    static void Main(string[] args)
    {
        Vehicle vehicle = new Car();
        vehicle.Run();
    }
}

abstract class VehicleBase
{
    public abstract void Stop();
    public abstract void Fill();
    public abstract void Run();
}

abstract class Vehicle : VehicleBase
{
    public override void Fill()
    {
        Console.WriteLine("pay and fill...");
    }

    public override void Stop()
    {
        Console.WriteLine("stopped!");
    }
}

class Car : Vehicle
{
    public override void Run()
    {
        Console.WriteLine("car is running...");
    }
}

class Truck : Vehicle
{
    public override void Run()
    {
        Console.WriteLine("truck is running...");
    }
}
純抽象類的優化

讓我們在思考下去,純抽象類,不就是介面的預設實現模式嗎,我們將純抽象類改成介面。

class Program
{
    static void Main(string[] args)
    {
        Vehicle vehicle = new Car();
        vehicle.Run();
    }
}

interface IVehicle
{
    void Stop();
    void Fill();
    void Run();
}

abstract class Vehicle : IVehicle
{
    public void Fill()
    {
        Console.WriteLine("pay and fill...");
    }

    public void Stop()
    {
        Console.WriteLine("stopped!");
    }
    abstract public void Run();
}

class Car : Vehicle
{
    public override void Run()
    {
        Console.WriteLine("car is running...");
    }
}

class Truck : Vehicle
{
    public override void Run()
    {
        Console.WriteLine("truck is running...");
    }
}
介面的優化

這是不是就熟悉多了,這是一種良好的設計方法了。