2026-05-17 C#面向對象編程(OOP)實戰練習

2026-05-17 C#面向對象編程(OOP)實戰練習

我:
using System;
using System.Collections;
using System.ComponentModel.Design;
using System.Runtime.CompilerServices;
using System.Security.Cryptography.X509Certificates;

#region 第六階段:面向對象編程(OOP)
//類別的定義範例
public class Person
{
public string Name=””;
public int Age;
public void Greet()
{
Console.WriteLine($”Hello, my name is {Name} and I am {Age} years old.”);
}
}

//改進的屬性(使用 get 和 set)
public class Car
{
// 使用屬性來封裝字段
public string Brand { get; set; } = string.Empty;

public string Color { get; set; } = string.Empty;


//方法
public void ShowCarInfo()
{
    Console.WriteLine($"This Car is a {Color} {Brand}.");
}

}

//建構函數的範例:
public class Person2
{
public string Name;
public int Age;
public Person2(string name , int age)
{
Name = name;
Age = age;
}
public void Greet()
{
Console.WriteLine($”Hello , my name is {Name} and I am {Age} years old.”);
}
}

//封裝 私有屬性和公開方法:
public class BankAccount
{
private decimal balance;

public void Deposit(decimal amount)
{
    balance += amount;
    Console.WriteLine($"存入{amount}元, 目前餘額為{balance}元");
}

public decimal GetBalance()
{ return balance; } 

}

//繼承-父
public class Animal
{
public void Eat()
{ Console.WriteLine(“Eating…”); }
}
//繼承-子
public class Dog: Animal
{
public void Bark()
{
Console.WriteLine(“Barking”);
}
}

//多態:
public class Animal1
{
public virtual void MakeSound()
{
Console.WriteLine(“Some generic animal sound”);
}
}

public class Cat: Animal1
{
public override void MakeSound()
{
Console.WriteLine(“Meow”);
}
}
//實戰練習
//練習 1:定義類別和創建物件

//定義一個類別 Book,包含屬性 Title 和 Author,以及方法 DisplayInfo,用來顯示書名和作者。
//使用這個類別創建一個物件,並輸出書的信息。
public class Book
{
public string Title { get; set; } = string.Empty;
public string Author { get; set; } = string.Empty;

public void DisplayInfo()
{
    Console.WriteLine($"This Book Title is【 {Title} 】and author is {Author}");
}

}

//練習 2:使用建構函數

//為 Book 類別添加建構函數,用來初始化 Title 和 Author。
//使用建構函數創建物件並輸出書的信息。
public class Book1
{
public string Title;
public string Author;
public Book1(string title, string author)
{
Title = title;
Author = author;
}
public void DisplayInfo()
{
Console.WriteLine($”This Book Title is 【 {Title} 】and author is {Author}”);
}
}

//練習 3:繼承與覆寫

//定義一個類別 Vehicle,包含方法 StartEngine。
//創建一個子類別 Car,繼承 Vehicle,並覆寫 StartEngine 方法以顯示特定的消息。
public class Vehicle
{
public virtual void StartEngine()
{
Console.WriteLine(“Engine Starting….”);
}
}

public class Car1 : Vehicle
{
public override void StartEngine()
{
Console.WriteLine(“Car’s Engine Starting…..”);
}
}
#endregion

class Program
{

static void Main(string[] args)
{


    #region  第六階段:面向對象編程(OOP)

    //創建物件範例:
    Person person1 = new Person();
    person1.Name = "Alice";
    person1.Age = 25;

    person1.Greet();

    //創建物件並設置屬性:
    Car mayCar = new Car();
    mayCar.Brand = "Toyota";
    mayCar.Color = "Red";

    mayCar.ShowCarInfo();

    //建構函數的範例:
    Person2 person2 = new Person2("Lily", 53);
    person2.Greet();


    //封裝 私有屬性和公開方法:
    BankAccount bankAccount = new BankAccount();
    decimal[] deposits = { 22908, 11201, 2333 };
    foreach (decimal amount in deposits)
    {
        bankAccount.Deposit(amount);
    }

    //繼承
    Dog myDog = new Dog();
    myDog.Eat(); // 繼承自父類別 Animal
    myDog.Bark();// 自己的方法

    //多態:
    Animal1 animal1 = new Animal1();
    animal1.MakeSound(); // 輸出: Some generic animal sound
    Cat myCat = new Cat();
    myCat.MakeSound(); // 輸出: Meow (多態)

    //實戰練習
    //練習 1:定義類別和創建物件

    //定義一個類別 Book,包含屬性 Title 和 Author,以及方法 DisplayInfo,用來顯示書名和作者。
    //使用這個類別創建一個物件,並輸出書的信息。
    Book myBook = new Book();
    myBook.Title = "Wonderful Day";
    myBook.Author = "Lily";
    myBook.DisplayInfo();

    //練習 2:使用建構函數

    //為 Book 類別添加建構函數,用來初始化 Title 和 Author。
    //使用建構函數創建物件並輸出書的信息。
    Book1 book1 = new Book1("Booking Time", "Amy");
    book1.DisplayInfo();

    //練習 3:繼承與覆寫

    //定義一個類別 Vehicle,包含方法 StartEngine。
    //創建一個子類別 Car,繼承 Vehicle,並覆寫 StartEngine 方法以顯示特定的消息。
    Vehicle myVehicle = new Vehicle();
    myVehicle.StartEngine();
    Car1 car1 = new Car1();
    car1.StartEngine();

    #endregion

}

}
問題
問題: 為什麼 OOP 中需要封裝數據?
通過訪問修飾符(例如 public、private)來控制屬性和方法的可見性,保護數據並隱藏實現細節。
例如:
public class BankAccount
{
private decimal balance;

public void Deposit(decimal amount)
{
    if (amount > 0)
    {
        balance += amount;
        Console.WriteLine($"存入 {amount} 元,目前餘額為 {balance} 元");
    }
}

public decimal GetBalance()
{
    return balance;
}

}

問題: 繼承如何幫助代碼的重用?
允許子類別從父類別繼承屬性和方法,從而實現代碼的重用。
例如:
public class Animal
{
public void Eat()
{
Console.WriteLine(“Eating…”);
}
}

public class Dog : Animal
{
public void Bark()
{
Console.WriteLine(“Barking…”);
}
}

class Program
{
static void Main(string[] args)
{
Dog myDog = new Dog();
myDog.Eat(); // 繼承自父類別 Animal
myDog.Bark(); // 自己的方法
}
}

GPT:
你的代碼已經很好地展示了面向對象編程(OOP)的各個方面,包括類別、屬性、方法、建構函數、封裝、繼承和多態。你還對 OOP 的問題進行了解釋,闡述了封裝繼承的優點。這裡有一些小的建議來讓你的代碼和回答更為精緻:

代碼優化和建議

  1. 屬性預設值與 null 檢查的改進

    • 你的屬性 NameTitleAuthor 等都有預設值 "",這可以防止 null,但如果你要明確禁止這些值為空字串,你可以進一步添加驗證邏輯。
    • 例如,你可以在 set 方法中進行檢查,確保值不為 null 或空字串。
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    public string Brand
    {
    get => _brand;
    set
    {
    if (string.IsNullOrWhiteSpace(value))
    {
    throw new ArgumentException("Brand cannot be empty or null.");
    }
    _brand = value;
    }
    }
    private string _brand = string.Empty;
  2. 建構函數改進

    • Person2 類別中,建構函數使用參數來初始化 NameAge,這是一個很好的設計模式。
    • 你可以考慮為 Book 類別中的 TitleAuthor 使用 required 屬性(C# 11 支持),這樣可以強制初始化屬性,使代碼更加安全。
  3. BankAccount 改進

    • Deposit 方法中,你應該檢查存款的金額是否為正數。已經有這樣的邏輯,但可以在 Deposit 內部返回新的餘額,這樣更方便使用。
    • 你也可以考慮添加一個 Withdraw 方法來支持取款功能,這樣 BankAccount 類別更接近真實世界的銀行帳戶。
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    public void Withdraw(decimal amount)
    {
    if (amount <= 0)
    {
    Console.WriteLine("取款金額必須大於 0.");
    return;
    }
    if (amount > balance)
    {
    Console.WriteLine("餘額不足,無法完成取款。");
    return;
    }
    balance -= amount;
    Console.WriteLine($"取出 {amount} 元,目前餘額為 {balance} 元");
    }
  4. 多態改進

    • 在多態的範例中,可以通過引入更多的子類別(例如 DogCat)來更好地展示多態的概念。
    • Main 方法中,你可以使用一個 List<Animal1> 來存儲不同的動物,並調用它們的 MakeSound 方法,這樣可以更好地展示多態的力量。
    1
    2
    3
    4
    5
    List<Animal1> animals = new List<Animal1> { new Animal1(), new Cat() };
    foreach (var animal in animals)
    {
    animal.MakeSound(); // 根據物件的具體型別調用對應的方法
    }

修正後的回答

問題 1:為什麼 OOP 中需要封裝數據?

回答:
封裝數據的主要目的是保護對象的內部狀態,防止外部程式直接訪問和修改內部的數據,從而維持系統的穩定性和安全性。通過使用訪問修飾符(例如 publicprivate),我們可以控制屬性和方法的可見性,並確保只有經過驗證或特定的方式才能修改數據。這樣做也有助於隱藏實現細節,使得類別對使用者來說更易於理解和使用。

範例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
public class BankAccount
{
private decimal balance;

public void Deposit(decimal amount)
{
if (amount > 0)
{
balance += amount;
Console.WriteLine($"存入 {amount} 元,目前餘額為 {balance} 元");
}
}

public decimal GetBalance()
{
return balance;
}
}

在這個範例中,balance 是私有的,只有通過 Deposit 方法和 GetBalance 方法才能存取和操作餘額。

問題 2:繼承如何幫助代碼的重用?

回答:
繼承允許子類別從父類別繼承屬性和方法,這樣可以實現代碼的重用,減少重複編寫相同功能的代碼。父類別中定義的所有屬性和方法都可以被子類別直接使用,而子類別也可以添加自己的特性或方法,或者覆寫父類別的方法來實現特殊化的行為。這種方式不僅減少了代碼重複,也使得程式的結構更有層次,更易於擴展。

範例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
public class Animal
{
public void Eat()
{
Console.WriteLine("Eating...");
}
}

public class Dog : Animal
{
public void Bark()
{
Console.WriteLine("Barking...");
}
}

class Program
{
static void Main(string[] args)
{
Dog myDog = new Dog();
myDog.Eat(); // 繼承自父類別 Animal
myDog.Bark(); // 自己的方法
}
}

在這個例子中,Dog 類別繼承了 Animal 類別,因此可以直接使用 Animal 類別的 Eat 方法,而不需要再次定義,從而實現了代碼重用。

小結

  • 你已經非常熟練地掌握了類別的定義、建構函數、封裝、繼承和多態等 OOP 的基礎概念。
  • 在進一步優化你的代碼時,可以考慮添加更多的驗證邏輯,使代碼更加健壯。
  • 多態可以讓不同的物件以相同的方式被操作,這樣程式變得更靈活。

接下來,如果你準備好了,我們可以進入第七階段,學習 接口(Interfaces)和抽象類(Abstract Classes),這是面向對象編程中進一步提升代碼抽象化和設計靈活性的重要工具。如果還有任何不清楚的地方,隨時告訴我!