C# 中的繼承:基類與派生類詳解
在面向?qū)ο缶幊蹋∣OP)中,繼承是一個核心概念。它允許一個類(派生類)繼承另一個類(基類)的屬性和方法,從而實現(xiàn)代碼的重用、封裝和多態(tài)性。C# 作為一種面向?qū)ο蟮木幊陶Z言,提供了強大的繼承機制。本文將詳細(xì)介紹基類與派生類的應(yīng)用特點和場景,并通過豐富的實例和注釋加深理解。
繼承的優(yōu)勢
代碼復(fù)用
通過繼承,派生類可以直接使用基類中已經(jīng)定義的屬性和方法,無需重復(fù)編寫相同的代碼,從而提高開發(fā)效率。
封裝
基類可以將一些不需要外部訪問的成員設(shè)為私有(private),只允許通過公共(public)方法來訪問,從而隱藏實現(xiàn)細(xì)節(jié),提高代碼的安全性。
多態(tài)
通過虛方法(virtual)和抽象方法(abstract),基類可以定義可在派生類中重寫(override)的方法,允許派生類表現(xiàn)出不同的行為。
繼承的應(yīng)用場景
建立類層次結(jié)構(gòu)
當(dāng)多個類共享相同的特性時,可以將這些共性抽象成一個基類,其他具有特定特性的類作為派生類。
實現(xiàn)接口替換原則
基類可以作為一個通用接口,允許在不改變外部代碼的情況下替換和擴展內(nèi)部實現(xiàn)。
設(shè)計模式的實現(xiàn)
很多設(shè)計模式(如工廠模式、策略模式等)都需要使用繼承來實現(xiàn)特定的功能和邏輯。
實例詳解
例1:基本繼承與代碼復(fù)用
namespace App05
{
// 基類:車輛
public class Vehicle
{
public string LicensePlate { get; set; }
public void StartEngine()
{
Console.WriteLine("發(fā)動機已啟動");
}
}
// 派生類:汽車
public class Car : Vehicle
{
public int NumberOfWheels { get; set; } = 4;
public void Honk()
{
Console.WriteLine("汽車?yán)龋亨洁剑?);
}
}
internal class Program
{
static void Main(string[] args)
{
// 使用示例
var car = new Car
{
LicensePlate = "粵A12345"
};
car.StartEngine(); // 繼承自基類的方法
car.Honk(); // 派生類的方法
Console.WriteLine($"車牌號:{car.LicensePlate}");
Console.WriteLine($"車輪數(shù):{car.NumberOfWheels}");
}
}
}
圖片
說明:
- Car 類繼承了 Vehicle 類,因此可以直接使用 Vehicle 中的屬性和方法,如 LicensePlate 和 StartEngine()。
- Car 類增加了自己的屬性 NumberOfWheels 和方法 Honk()。
例2:方法重寫與多態(tài)
namespace App05
{
// 基類:動物
public class Animal
{
public virtual void Speak()
{
Console.WriteLine("某種動物的叫聲");
}
}
// 派生類:狗
public class Dog : Animal
{
public override void Speak()
{
Console.WriteLine("汪汪!");
}
}
// 派生類:貓
public class Cat : Animal
{
public override void Speak()
{
Console.WriteLine("喵喵!");
}
}
internal class Program
{
static void Main(string[] args)
{
// 使用示例
Animal animal;
animal = new Dog();
animal.Speak(); // 輸出 "汪汪!"
animal = new Cat();
animal.Speak(); // 輸出 "喵喵!"
}
}
}
圖片
說明:
- 在基類 Animal 中,Speak() 方法被聲明為 virtual,表示它可以在派生類中被重寫。
- 在派生類 Dog 和 Cat 中,Speak() 方法使用 override 關(guān)鍵字進行重寫,從而表現(xiàn)出不同的行為。
- 通過將 animal 聲明為 Animal 類型,可以實現(xiàn)多態(tài)性的效果。
例3:抽象類與多態(tài)
namespace App05
{
// 抽象基類:形狀
public abstract class Shape
{
public abstract double Area();
}
// 派生類:圓形
public class Circle : Shape
{
public double Radius { get; set; }
public override double Area()
{
return Math.PI * Radius * Radius;
}
}
// 派生類:矩形
public class Rectangle : Shape
{
public double Width { get; set; }
public double Height { get; set; }
public override double Area()
{
return Width * Height;
}
}
internal class Program
{
static void Main(string[] args)
{
// 使用示例
Shape circle = new Circle { Radius = 5 };
Console.WriteLine($"圓的面積:{circle.Area()}");
Shape rectangle = new Rectangle { Width = 4, Height = 6 };
Console.WriteLine($"矩形的面積:{rectangle.Area()}");
}
}
}
圖片
說明:
- Shape 類被聲明為抽象類,不能被實例化,只能被繼承。
- Area() 方法是一個抽象方法,必須在派生類中進行重寫。
- Circle 和 Rectangle 分別重寫了 Area() 方法,實現(xiàn)了特定形狀的面積計算。
例4:訪問修飾符與封裝
// 基類:賬戶
public class Account
{
private decimal balance;
public void Deposit(decimal amount)
{
balance += amount;
Console.WriteLine($"存入:{amount},余額:{balance}");
}
public void Withdraw(decimal amount)
{
if (amount <= balance)
{
balance -= amount;
Console.WriteLine($"取出:{amount},余額:{balance}");
}
else
{
Console.WriteLine("余額不足!");
}
}
// 受保護的方法,可供派生類訪問
protected decimal GetBalance()
{
return balance;
}
}
// 派生類:儲蓄賬戶
public class SavingsAccount : Account
{
private decimal interestRate = 0.01m; // 利率1%
public void ApplyInterest()
{
decimal interest = GetBalance() * interestRate;
Deposit(interest);
Console.WriteLine($"已應(yīng)用利息:{interest}");
}
}
// 使用示例
var savings = new SavingsAccount();
savings.Deposit(1000); // 存入初始金額
savings.ApplyInterest(); // 應(yīng)用利息
savings.Withdraw(500); // 取出部分金額
圖片
說明:
- Account 類的 balance 字段被聲明為 private,只能在類內(nèi)部訪問。
- 通過 protected 方法 GetBalance(),SavingsAccount 可以訪問 balance 的值。
- SavingsAccount 類新增了方法 ApplyInterest(),用于計算并應(yīng)用利息。
例5:多級繼承
namespace App05
{
// 基類:電子產(chǎn)品
public class Electronic
{
public void TurnOn()
{
Console.WriteLine("設(shè)備已打開");
}
}
// 派生類:電腦
public class Computer : Electronic
{
public void Boot()
{
Console.WriteLine("電腦正在啟動");
}
}
// 派生類:筆記本電腦
public class Laptop : Computer
{
public void Fold()
{
Console.WriteLine("筆記本電腦可以折疊");
}
}
internal class Program
{
static void Main(string[] args)
{
// 使用示例
var laptop = new Laptop();
laptop.TurnOn(); // 繼承自 Electronic
laptop.Boot(); // 繼承自 Computer
laptop.Fold(); // 自身的方法
}
}
}
圖片
說明:
- 通過多級繼承,Laptop 類繼承了 Computer 和 Electronic 類的屬性和方法。
四、總結(jié)
在本文中,我們深入學(xué)習(xí)了 C# 中基類與派生類的概念,理解了繼承的優(yōu)勢以及應(yīng)用場景。通過豐富的實例和詳細(xì)的注釋,展示了如何在實際編程中使用繼承來實現(xiàn)代碼復(fù)用、封裝和多態(tài)性。
在設(shè)計自己的類層次結(jié)構(gòu)時,應(yīng)考慮如何有效地利用繼承來優(yōu)化代碼的結(jié)構(gòu)和可重用性。然而,需要注意的是,過度使用繼承可能會導(dǎo)致代碼的復(fù)雜性增加,應(yīng)根據(jù)實際需求進行合理設(shè)計。
建議:
- 在使用繼承時,優(yōu)先考慮類之間是否存在顯式的“是一個”(is-a)關(guān)系。
- 如果只是需要某些功能,而不需要繼承整個類,可以考慮使用接口(interface)或組合(composition)。