跳過到頁腳內容
Iron Academy Logo
學習 C#
學習 C#

其他分類

理解 C# 抽象類

Tim Corey
19m 59s

C#中的抽象類別是一個基本概念,經常引發開發者的提問。 在他的視頻中,"C# 抽象類別——它們是什麼、如何使用它們及最佳實踐",Tim Corey 深入探討了抽象類別是什麼,如何使用它們,以及最佳實踐。 本文總結了他視頻中的要點,並使用了時間戳作為參考。

介紹

Tim (0:00) 解釋了抽象類別經常被質疑的目的、功能和重要性。 他將抽象類別描述為一個介於完整基類和介面之間的結合體,在功能上位於兩者之間。

演示應用程序走過

在 (0:59),Tim 透過一個展示應用來演示抽象類別。 該應用包括一個控制台應用和一個類別庫,其中有兩個模擬資料庫操作的數據訪問類別。 這些類別具有用於載入和儲存數據的方法,Tim 用這些來說明抽象類別、基類和介面之間的相似點和區別。

以下是基類和派生類的初始代碼:

// Base Class Definition
public class DataAccess
{
    // Method to load the connection string
    public string LoadConnectionString()
    {
        Console.WriteLine("Loading the connection string...");
        return "Test Connection String";
    }

    // Method to load data
    public void LoadData()
    {
        Console.WriteLine("Loading data...");
    }

    // Method to save data
    public void SaveData()
    {
        Console.WriteLine("Saving data...");
    }
}

// Derived class that inherits from DataAccess
public class SQLDataAccess : DataAccess
{
    // Overriding LoadData method to specify SQL data loading
    public new void LoadData()
    {
        Console.WriteLine("Loading SQL data...");
    }

    // Overriding SaveData method to specify SQL data saving
    public new void SaveData()
    {
        Console.WriteLine("Saving SQL data...");
    }
}

// Derived class that inherits from DataAccess
public class SQLiteDataAccess : DataAccess
{
    // Overriding LoadData method to specify SQLite data loading
    public new void LoadData()
    {
        Console.WriteLine("Loading SQLite data...");
    }

    // Overriding SaveData method to specify SQLite data saving
    public new void SaveData()
    {
        Console.WriteLine("Saving SQLite data...");
    }
}
// Base Class Definition
public class DataAccess
{
    // Method to load the connection string
    public string LoadConnectionString()
    {
        Console.WriteLine("Loading the connection string...");
        return "Test Connection String";
    }

    // Method to load data
    public void LoadData()
    {
        Console.WriteLine("Loading data...");
    }

    // Method to save data
    public void SaveData()
    {
        Console.WriteLine("Saving data...");
    }
}

// Derived class that inherits from DataAccess
public class SQLDataAccess : DataAccess
{
    // Overriding LoadData method to specify SQL data loading
    public new void LoadData()
    {
        Console.WriteLine("Loading SQL data...");
    }

    // Overriding SaveData method to specify SQL data saving
    public new void SaveData()
    {
        Console.WriteLine("Saving SQL data...");
    }
}

// Derived class that inherits from DataAccess
public class SQLiteDataAccess : DataAccess
{
    // Overriding LoadData method to specify SQLite data loading
    public new void LoadData()
    {
        Console.WriteLine("Loading SQLite data...");
    }

    // Overriding SaveData method to specify SQLite data saving
    public new void SaveData()
    {
        Console.WriteLine("Saving SQLite data...");
    }
}

建立基類

Tim 在 (3:21) 解釋了如何建立基類。 他重構代碼以將公共方法(例如 LoadConnectionString)移到一個名為 DataAccess 的基類中。 通過從此基類繼承,像 SQLDataAccessSQLiteDataAccess 這樣的其他類別可以訪問這些共享的方法,從而減少代碼重複。

將基類變為抽象類別

Tim 在 (5:56) 將基類轉變為抽象類別,以展示其不同之處。 他將 DataAccess 改變成一個抽象類別,防止直接實例化。 相反,只有從此抽象類別繼承的類別(如 SQLiteDataAccessSQLDataAccess)才能實現其方法並使用其共享功能。

以下是 DataAccess 成為抽象類別後的代碼變化:

// Abstract Base Class Definition
public abstract class AbstractDataAccess
{
    // Shared method to load connection string
    public string LoadConnectionString()
    {
        Console.WriteLine("Loading the connection string...");
        return "Test Connection String";
    }

    // Abstract methods that must be implemented by derived classes
    public abstract void LoadData();
    public abstract void SaveData();
}
// Abstract Base Class Definition
public abstract class AbstractDataAccess
{
    // Shared method to load connection string
    public string LoadConnectionString()
    {
        Console.WriteLine("Loading the connection string...");
        return "Test Connection String";
    }

    // Abstract methods that must be implemented by derived classes
    public abstract void LoadData();
    public abstract void SaveData();
}

抽象類別中的介面部分

Tim 在 (8:34) 解釋了抽象類別如何結合介面和基類的特徵。 他在抽象類別中聲明了抽象方法(如 public abstract void LoadData();public abstract void SaveData();),但不實現它們。 這確保所有派生類必須實現這些方法,類似於介面的運作方式。

覆蓋抽象類別中的方法

Tim 在 (12:56) 討論了如何覆蓋抽象類別中的方法。 他展示了可以在基類中宣告一個方法為 virtual,允許派生類覆蓋它。 這種方法提供了方法在派生類中的實現和擴展靈活性。

以下是顯示方法覆蓋的派生類代碼:

// Derived class from abstract base class
public class SQLDataAccessWithAbstract : AbstractDataAccess
{
    // Implementing the abstract LoadData method
    public override void LoadData()
    {
        Console.WriteLine("Loading SQL data...");
    }

    // Implementing the abstract SaveData method
    public override void SaveData()
    {
        Console.WriteLine("Saving SQL data...");
    }
}
// Derived class from abstract base class
public class SQLDataAccessWithAbstract : AbstractDataAccess
{
    // Implementing the abstract LoadData method
    public override void LoadData()
    {
        Console.WriteLine("Loading SQL data...");
    }

    // Implementing the abstract SaveData method
    public override void SaveData()
    {
        Console.WriteLine("Saving SQL data...");
    }
}

何時使用抽象類別

Tim 在 (16:01) 建議不應每天都使用抽象類別,但在特定情況下是有價值的。 他警告不要僅僅因為兩個類別有相似的代碼而使用抽象類別。 相反,他強調維護"是"關係,並建議在適用的情況下考慮使用輔助方法或類別來處理共享代碼。

以下是展示用法的主程式代碼:

// Main Program
class Program
{
    static void Main(string[] args)
    {
        // Using Base Class
        SQLDataAccess sqlData = new SQLDataAccess();
        Console.WriteLine(sqlData.LoadConnectionString());
        sqlData.LoadData();
        sqlData.SaveData();

        Console.WriteLine("--------------------------");

        // Using Derived Class from Abstract Base Class
        SQLDataAccessWithAbstract sqlDataAbstract = new SQLDataAccessWithAbstract();
        Console.WriteLine(sqlDataAbstract.LoadConnectionString());
        sqlDataAbstract.LoadData();
        sqlDataAbstract.SaveData();

        Console.WriteLine("--------------------------");

        // You can't instantiate Abstract Base Class directly
        // AbstractDataAccess abstractData = new AbstractDataAccess(); 
        // Error: Cannot create an instance of the abstract class
    }
}
// Main Program
class Program
{
    static void Main(string[] args)
    {
        // Using Base Class
        SQLDataAccess sqlData = new SQLDataAccess();
        Console.WriteLine(sqlData.LoadConnectionString());
        sqlData.LoadData();
        sqlData.SaveData();

        Console.WriteLine("--------------------------");

        // Using Derived Class from Abstract Base Class
        SQLDataAccessWithAbstract sqlDataAbstract = new SQLDataAccessWithAbstract();
        Console.WriteLine(sqlDataAbstract.LoadConnectionString());
        sqlDataAbstract.LoadData();
        sqlDataAbstract.SaveData();

        Console.WriteLine("--------------------------");

        // You can't instantiate Abstract Base Class directly
        // AbstractDataAccess abstractData = new AbstractDataAccess(); 
        // Error: Cannot create an instance of the abstract class
    }
}

結論

Tim Corey 對 C# 抽象類別 的深入研究提供了對其目的、功能及實際應用的清晰和實用的理解。 透過他的展示應用,他展示了抽象類別如何在基類和介面之間架橋,讓開發者能夠創建靈活且易於維護的代碼結構。

通過強調最佳實踐,諸如在適當情境下使用抽象類別並避免過度使用,Tim 為開發者提供了做出明智設計選擇的工具。 掌握這些概念後,開發者可以增強其面向對象編程的技能,並構建強大的 C# 應用。

Hero Worlddot related to 理解 C# 抽象類
Hero Affiliate related to 理解 C# 抽象類

通過分享您所愛的東西賺得更多

您是否在為使用.NET、C#、Java、Python或Node.js的開發者創建內容?將您的專業知識轉化為額外收入!

鋼鐵支援團隊

我們每週 5 天,每天 24 小時在線上。
聊天
電子郵件
打電話給我