跳至頁尾內容
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)解釋了如何建立基底類別。 他重構了程式碼,將DataAccess的基底類別中。 透過繼承此基底類別,像SQLiteDataAccess這樣的其他類別可以存取這些共享方法,減少程式碼重複。

將基底類別改為抽象類別

Tim在(5:56)將基底類別轉換成抽象類別以展示差異。 他將DataAccess更改為抽象類別,以防止其直接實例化。 相反,只有繼承此抽象類別的類別,例如SQLDataAccess,可以實現其方法並使用其共享功能。

以下是當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 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 的開發者建立內容?將您的專業知識轉化為額外收入!

Iron 支援團隊

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