一、面向對象與面向過程的核心區別(概念鋪墊)
代碼背景
開篇對比了兩種編程范式:
面向過程(PP):按步驟分解問題(如 “輸入長→輸入寬→計算面積”);
面向對象(OOP):將問題抽象為 “對象”,通過對象的屬性和行為解決問題(如 “矩形對象” 有長、寬屬性和計算面積的方法)。
補充知識點
編程范式:是解決問題的 “方法論”,OOP 更適合復雜系統(可維護性、復用性強),PP 適合簡單流程(如腳本工具)。
對象的核心特征:狀態(屬性) 和行為(方法) 的封裝。例如 “人” 的屬性是姓名、年齡,行為是吃飯、睡覺。
二、類與對象的基礎定義(Rectangle 類示例)
代碼解析
class Rectangle ?// 類定義 {public int Length; ?// 屬性(字段)public int Width; ? public int Area() ?// 方法{return Length * Width;} } ? // 實例化對象并使用 Rectangle rectangle = new Rectangle(); ? rectangle.Length = 5; ? rectangle.Width = 3; ? Console.WriteLine(rectangle.Area()); ?// 輸出15
補充知識點
類的本質:“模板” 或 “藍圖”,定義對象的 “能有什么”(屬性)和 “能做什么”(方法)。
對象的實例化:
new 類名()
是創建對象的語法,本質是在內存中分配空間,初始化屬性。成員訪問:通過
對象.成員
訪問屬性或調用方法,體現對象的 “自主性”。
三、類的創建與結構(People 類示例)
代碼解析
class People ?// 類定義(默認internal修飾符) {string name; ?// 私有字段(默認private)int age; ? ? ?void eat() ? ?// 私有方法{Console.WriteLine("吃飯");} }
補充知識點
類的結構三要素:
字段(成員變量):存儲對象的狀態(如
name
、age
);方法:定義對象的行為(如
eat()
);訪問修飾符:控制成員的可訪問范圍(核心是封裝)。
訪問修飾符作用:
public
:任何地方可訪問(如對外暴露的接口);private
:僅類內部可訪問(如內部計算的臨時變量);internal
:僅當前項目可訪問(如項目內共享的工具類)。
訪問修飾符 / 范圍 | 當前類 | 父類 | 實例對象 | 引用當前項目的項目子類 | 引用當前項目實例對象 | 同一程序集的非子類 | 不同程序集的子類 | 不同程序集的非子類 |
---|---|---|---|---|---|---|---|---|
public | √ | √ | √ | √ | √ | √ | √ | √ |
private | √ | × | × | × | × | × | × | × |
internal | √ | √ | √ | √ | √ | √ | × | × |
protected | √ | √ | × | √ | × | × | √ | × |
protected internal | √ | √ | × | √ | √ | √ | √ | × |
private protected | √ | × | × | √ (僅同一程序集) | × | × | × (不同程序集) | × |
四、對象的實例化與成員訪問(People 對象示例)
代碼解析
// 實例化對象 People p1 = new People(); ? p1.name = "吳亦凡"; ?// 訪問公共字段(需先將name改為public) ? // 對象初始化器(語法糖) People p2 = new People() { name = "羅志祥" }; ? ? // 調用方法 p1.eat(); ? People.sleep(); ?// 調用靜態方法
補充知識點
對象初始化器:
new 類名() { 成員 = 值 }
簡化對象屬性賦值,本質是先調用構造函數,再賦值。靜態成員訪問:靜態方法 / 屬性屬于類本身(如
People.sleep()
),無需實例化對象,通過類名.成員
訪問;非靜態成員屬于對象(如p1.eat()
),必須通過實例訪問。
五、屬性與字段的封裝(Student、Dog 類示例)
代碼解析
class Student {private char _sex; ?// 私有字段(內部存儲)public char Sex ? ? // 公共屬性(外部訪問接口){get { return _sex; } ?// 獲取值set ? ? ? ? ? ? ? ? ? // 設置值(帶驗證){if (value == '男' || value == '女')_sex = value;elsethrow new Exception("性別必須是男或女");}} }
補充知識點
封裝的核心體現:用私有字段存儲數據,通過公共屬性控制訪問,避免外部直接修改導致數據混亂(如年齡不能為負、性別只能是男女)。
屬性的訪問器:
get
:返回字段值(可添加邏輯,如計算后返回);set
:接收外部傳入的value
(需與屬性類型一致),可添加驗證邏輯。
字段與屬性的本質區別:
字段是 “容器”(直接存數據);
屬性是 “接口”(不存數據,通過
get/set
操作字段,實現數據保護)。
六、構造函數與對象初始化(People 類構造函數示例)
代碼解析
class People {public string Name { get; set; }public int Age { get; set; } ?// 無參構造函數public People(){Console.WriteLine("無參構造執行");} ?// 有參構造函數(重載)public People(string name, int age){Name = name;Age = age;} }
補充知識點
構造函數作用:對象實例化時自動執行,用于初始化對象(如設置默認值、驗證參數)。
構造函數重載:同一類中多個構造函數,參數列表不同(體現多態),滿足不同初始化需求(如無參構造用默認值,有參構造自定義值)。
默認構造函數:若未手動定義構造函數,編譯器自動生成無參構造;若定義了有參構造,默認無參構造會被覆蓋,需手動添加。
七、析構函數與垃圾回收(People 析構函數示例)
代碼解析
class People {~People() ?// 析構函數{Console.WriteLine("析構函數執行");} } ? // 觸發垃圾回收 People p1 = new People(); ? p1 = null; ?// 解除引用 GC.Collect(); ?// 強制回收
補充知識點
析構函數作用:對象被垃圾回收(GC)時自動執行,用于釋放非托管資源(如文件句柄、數據庫連接)。
GC 機制:C# 自動管理內存,當對象無引用時,GC 會在合適時機回收內存,析構函數執行時機不可控,因此優先使用
IDisposable
接口手動釋放資源。
八、靜態成員與實例成員(People 靜態成員示例)
代碼解析
class People {public string Name1 { get; set; } ?// 實例屬性public static string Name2 { get; set; } ?// 靜態屬性 ?public void Test1() ?// 實例方法{Console.WriteLine(Name1); ?// 可訪問實例和靜態成員Console.WriteLine(Name2);} ?public static void Test2() ?// 靜態方法{// Console.WriteLine(Name1); 錯誤:靜態方法不能訪問實例成員Console.WriteLine(Name2); ?// 只能訪問靜態成員} }
補充知識點
靜態成員特性:
屬于類,所有對象共享一份(如計數器、工具方法);
生命周期與程序一致(程序啟動時加載,結束時釋放);
靜態方法中無
this
指針(因不依賴對象)。
應用場景:工具類(如
Math
)、全局配置(如AppConfig
)、單例模式等。
九、常量與只讀成員(Test 類示例)
代碼解析
class Test {public const int c = 2; ?// 常量(編譯期確定)public readonly int a = 1; ?// 只讀字段(運行期確定) ?public Test(){a = 10; ?// 只讀字段可在構造函數中賦值} ?private string _d = "1";public string D { get => _d; } ?// 只讀屬性(無set) }
補充知識點
const 與 readonly 區別:
const
:編譯時確定值,必須聲明時賦值,可用于字段 / 局部變量;readonly
:運行時確定值,可在聲明或構造函數中賦值,僅用于字段。
只讀屬性:僅保留
get
訪問器(如D
),確保屬性只能被讀取,無法外部修改,增強封裝。
十、繼承與派生(People→Student→SamllStudent 示例)
代碼解析
// 基類 class People {public string Name { get; set; }public void Eat() { Console.WriteLine("吃飯"); } }// 派生類 class Student : People // 繼承語法:派生類:基類 {public string StudentId { get; set; } // 新增屬性public void Study() { Console.WriteLine("學習"); } }// 繼承鏈:SamllStudent → Student → People → object class SamllStudent : Student { }
補充知識點
繼承核心作用:代碼復用(子類繼承父類所有成員,除構造函數、析構函數)。
C# 繼承特性:
單繼承:一個類只能直接繼承一個基類(避免菱形繼承問題);
傳遞性:
SamllStudent
間接繼承People
的成員;向上轉型:
People p = new Student()
(子類對象可賦值給父類變量,體現多態)。
十一、作業:Aircraft 類的完整封裝(綜合應用)
代碼核心模塊解析
public class Aircraft {// 1. 私有字段(內部存儲)private string _brand;private int _loadCapacity; // 最大裝載人數private string _aircraftType; // 飛機類型private int _currentLoad; // 當前裝載人數// 2. 公共屬性(外部訪問接口,帶驗證)public int LoadCapacity{get => _loadCapacity;set{if (value < 0) throw new ArgumentException("最大裝載人數不能為負");_loadCapacity = value;CalculateAircraftType(); // 自動計算類型GenerateCurrentLoad(); // 生成當前人數}}public string AircraftType => _aircraftType; // 只讀屬性// 3. 構造函數(初始化)public Aircraft(string brand, int loadCapacity){_brand = brand;LoadCapacity = loadCapacity; // 觸發類型計算}// 4. 私有方法(內部邏輯)private void CalculateAircraftType(){_aircraftType = _loadCapacity > 400 ? "大型" : (_loadCapacity > 200 ? "中型" : "小型");}private void GenerateCurrentLoad(){_currentLoad = new Random().Next(1, _loadCapacity + 1); // 隨機生成}// 5. 公共方法(對外行為)public void TakeOff(){Console.WriteLine($"{_brand}起飛,當前裝載{_currentLoad}人");} }
知識點綜合應用
封裝:通過
LoadCapacity
屬性的set
訪問器驗證輸入合法性,確保_loadCapacity
不為負。自動邏輯:設置
LoadCapacity
時自動觸發CalculateAircraftType
(根據人數分類型)和GenerateCurrentLoad
(隨機生成當前人數),體現對象的 “自主性”。只讀屬性:
AircraftType
僅暴露get
,確保類型由內部邏輯計算,外部無法修改。構造函數:通過有參構造函數初始化核心屬性,簡化對象創建流程。
總結
面向對象編程的核心是 “抽象” 與 “封裝”:通過類抽象事物的共性,通過對象實例化具體事物,通過訪問修飾符、屬性、方法控制數據和行為的訪問,最終實現高內聚、低耦合的代碼設計。Aircraft 類綜合應用了字段、屬性、構造函數、方法等要素,是面向對象思想的典型實踐。