第九單元 面向對象一:類與對象

来源:https://www.cnblogs.com/xuyubing/archive/2023/05/30/17442885.html
-Advertisement-
Play Games

假設,班級里40位同學,我們用程式保存40位學生的信息:學號,姓名,性別,生日,身份證號。如果是你,你會怎麼實現? 小菜同學拿到這個題,奮書疾筆,馬上寫出如下代碼: ArrayList list = new ArrayList(); ​ string stuNo1="10001"; string n ...


假設,班級里40位同學,我們用程式保存40位學生的信息:學號,姓名,性別,生日,身份證號。如果是你,你會怎麼實現?

小菜同學拿到這個題,奮書疾筆,馬上寫出如下代碼:

ArrayList list = new ArrayList();
​
string stuNo1="10001";
string name1 = "張三";
string sex="男";
Datetime birthday1 = Datetime.Parse("1998-08-08");
string idCard1 = "362530199808080510";
list.add(stuNo1);
list.add(name1);
... list.add....
    
........//經過1個半小時後,終於到了第40位。

 

那如果是有4000,4萬?你是不是立馬從入門到卸載了?面向對象來告訴你解決方案!!

1. 面向對象概念

面向對象編程( OOP,Object Oriented Programming

  • 並不是一個技術,而是一種編程指導思想。

  • 把現實世界的具體事物全部看成一個一個的對象來解決實際問題。

為什麼要用面向對象編程

生活中我們解決問題就是按照對象化的方式進行的。如果程式也能夠按照生活的中的方式來解

決問題,那麼程式就更符合人類的思維習慣,代碼看起來會更易理解、更簡單、更易維護。

 

面向對象編程共同三大特性:封裝,繼承,多態。

在C# 中,一定要時刻的牢記這句話:一切皆為object(對象);

2. 封裝

封裝 被定義為"把一個或多個項目封閉在一個物理的或者邏輯的包中"。在面向對象程式設計方法論中,封裝是為了防止對實現細節的訪問。

抽象和封裝是面向對象程式設計的相關特性。抽象允許相關信息可視化,封裝則使開發者實現所需級別的抽象

訪問修飾符

C# 封裝根據具體的需要,設置使用者的訪問許可權,並通過 訪問修飾符 來實現。

一個 訪問修飾符 定義了一個類成員的範圍和可見性。C# 支持的訪問修飾符如下所示:

  • public:所有對象都可以訪問;

  • private:對象本身在對象內部可以訪問;

  • protected:只有該類對象及其子類對象可以訪問

  • internal:同一個程式集的對象可以訪問;

  • protected internal:訪問限於當前程式集或派生自包含類的類型。

img

實現封裝的方式共有三種:類的封裝,屬性封裝,方法的封裝。

封裝的作用:

  • 隱藏細節,設置訪問許可權,提高安全性

  • 代碼復用。

  • 提高代碼的可讀性

3. 什麼是類

類是一組具有相同事物和行為的抽象(物以類聚)。

類在實現生活中是不存在的,看不見,摸不著。例如:人類,狗類,貓科類,靈長類.... 這些事物都只是一些抽象的概念,並不是指具體的物體。如果我說:小明今天吃了三碗飯,小紅的頭髮很長,那麼,小明,小紅 是指人類的具體對象,lucky(一隻貓) 這個月身體長得很快,這也指的是對象,因為lucky是實實在在存在的。

人為什麼不和狗分為一類?

答:因為人和狗的體徵行為都不一樣!!再次強調類:類是一組具有相同事物和行為的抽象(物以類聚)。人會思考,人會製作工具,而狗不會。

 

對象:是真實存在的具體實例。

類(設計圖):是對象共同特征的描述(抽象)。

 

在C#中,必須先設計類,才能獲得對象。

 

4. 如何定義類

定義類的關鍵字是class,命名規範為首字母大寫,以帕斯卡(大駝峰)方式命名 如:

<訪問修飾符> class 類名
{
    // 構造器(下一個單元會講到)
    
    // 欄位
    
    // 屬性(特征)
    
    // 方法(行為)
    
    // 事件(C# 高級階段學習)
    
    // 索引器(c# 高級階段學習)
    
}

如:
public class Person
{
    // 欄位
    private string name;
    
    // 屬性
    public string Name
    {
        get
        {
            return name;
        }
        set
        {
            value=name;
        }
    }
    
    // 方法
    public void eat()
    {
        Console.WriteLine("吃飯,我要吃油燜大蝦");
    }
}

 

其中,欄位,屬性,方法,被統稱為類的成員。欄位,屬性 被稱為成員變數,方法被稱為成員方法

訪問標識符 <access specifier> 指定了對類及其成員的訪問規則。如果沒有指定,則使用預設的訪問標識符。類的預設訪問標識符是 internal,成員的預設訪問標識符是 private

5. 欄位與屬性

欄位一般是私有的(private),屬於類的私有信息,如:姓名,年齡,身份證號等等信息都是屬於人類的私有信息。

public class Person
{
    private string name;
    private int age;
}

 

屬性是類對外提供訪問欄位的途徑,一般是公有的(public) ,如:別人問你年齡,女孩子一般說18歲。此時她說的18歲是她自己對外主動暴露出來的,事實上她的真實年齡信息是私有的,只有她自己知道,到底是不是18歲我們其實是不清楚的。

public class Person
{
    private string name;
    private int age;
    
    public string Name
    {
        // get 訪問器
        get
        {
            return name;
        }
        // set 訪問器
        set
        {
            value=name;
        }
    }
    
    public int Age
    {
        get
        {
            return 18;
        }
        set
        {
            value = age;
        }
    }
}

Get, Set 訪問器都可以設置訪問修飾符哦,預設的訪問修飾符都是public.

c# 9.0 之後 還支持 Init訪問器, 調用方可使用屬性初始化表達式語法 , 在創建表達式中設置這些值 。 但構造完成後,這些屬性將變為只讀

 

欄位與屬性的區別

  • 欄位是私有的(private),屬性是公開的(public)。

  • 屬性具有讀寫器( get, set)

  • 欄位命名,以小駝峰命名,屬性以帕斯卡(大駝峰)命名。

  • 屬性並沒有真正存儲數據

只讀屬性

也就是只提供了, Get 訪問器,沒有Set 訪問器。

public class Person
{
    private short orderState
    
    public string OrderState
    {
        get
        {
            switch(orderState){
                case 1:
                    return "待支付";
                case 2:
                    return "待發貨";
                case 3:
                    return "待收貨";
                case 4:
                    return "已完成";
                default:
                    return "待支付";
            }
        }
    }
}

 

只寫屬性

也就是只提供了, Set 訪問器,沒有Get 訪問

public class Person
{
    private string pwd
    
    public string Password
    {
        set { value = pwd;} // 沒有Get
    }
}

 

屬性簡寫

如果一個類中,屬性只是直接對欄位進行讀寫,那麼,這個屬性欄位就可進行簡寫。

例如:

public class Person
{
    private string name;
    private int age;
    
    public string Name
    {
        get { return name; }
        set { value=name; }
    }
    
    public int Age
    {
        get { return 18; }
        set { value = age; }
    }
}
// 簡化後
public class Person
{
    public string Name {get; set;}
    public int Age {get; set;}
}

 

我們剛說過,屬性是對欄位的封裝,但是簡寫後的屬性根本就看不到類,豈不是自相矛盾嗎?其實簡寫屬性中其實隱藏了欄位,如果通過反編譯工具編譯 MS IL 或者通過反射技術去查看,我們會可以將它隱藏的欄位讀取出來。

6. 類的對象(實例)

語法:

類名 對象名 = new 類名();
如:
Person per = new Person();

  

使用對象

訪問屬性: 對象名.成員屬性
訪問行為: 對象名.方法名(…)

 

例如:

public class Person
{
    private string name
    
    public string Name
    {
        set { value = name;}
        get { return name;}
    }
    
    public void Eat()
    {
        Console.WriteLine($"姓名:{name},他正在吃飯..");
    }
}
class Program
{
    static void Main(string[] args)
    {
        Person per1 = new Person();
        per1.Name = "張三"; // 訪問屬性
        per1.Eat();  // 調用成員方法
        
        Person per2 = new Person();
        per2.Name = "李四"; // 訪問屬性
        per2.Eat();  // 調用成員方法
    }
}

輸出結果:

姓名:張三,他正在吃飯..
姓名:李四,他正在吃飯..

  

7. 構造方法

學構造方法的目的?

  • 真正知道對象具體是通過什麼得到的。

  • 能夠掌握為對象賦值的其他寫法。

構造方法的作用

  • 用於初始化一個類的對象,並返回對象的地址。

  • 簡化對象初始化的過程

語法

修飾符 類名(形參列表)
{
	...
}

public class Car 
{
    ...
    // 無參數構造器
    public Car()
    {
    	...
    }
    // 有參數構造器
    public Car(String n, String b)
    {
    	...
    } 
}

  

初始化對象的格式

類名 對象名稱 = new 構造器;
Car c = new Car();

  

構造器的分類

  • 無參數構造器(預設存在的):初始化的對象時,成員變數的數據均採用預設值。

  • 有參數構造器:在初始化對象的時候,同時可以為對象進行賦值。

註意事項

  • 任何類定義出來,預設就自帶了無參數構造器,寫不寫都有。

  • 一旦定義了有參數構造器,無參數構造器就沒有了,此時就需要自己寫一個無參數構造器了。

public class Car 
{
	...
	// 無參數構造器(預設存在的) 
}

public class Car 
{
    ...
    public Car()
    {
        // 無參數構造器(需要寫出來了)
    }    
    public Car(String n, String b)
    {
        // 有參數構造器
	} 
}

 

8. 兩個變數指向同一個對象

class Student
{
    public string Name { get; set; }
    public string Sex  { get; set; }
    public string Hobby  { get; set; }
    
    public void Study()
    {
        Console.WriteLine($"姓名:{Name},性別:{Sex},愛好:{Hobby}");
    }
}
public static void main(String[] args) 
{
    Student s1 = new Student();
    s1.Name = "小明";
    s1.Sex = '';
    s1.Hobby = "游戲、睡覺、聽課";
    s1.Study();
    // 把學生類型的s1變數賦值給學生類型的s2變數
    Student s2 = s1;
    s2.Hobby = "愛提問";
    
    Console.WriteLine(s2.Name);
    Console.WriteLine(s2.Sex);
    
    Console.WriteLine(s1.Hobby);
    s2.Study();
}

 

輸出結果:

姓名:小明,性別:男,愛好:游戲、睡覺、聽課
小明
男
愛提問
姓名:小明,性別:男,愛好:愛提問

  

記憶體分佈圖

思考:如果某個對象,被當作方法參數傳遞之後,在方法體內對象(形參)的某些屬性被修改,那麼實參對象的屬性會發生變化嗎?

9. this 關鍵字

假設有如下一段代碼:

public class Person
{
    private string name;
    private string age;
    public Person(string name,string age)
    {
        name = name; // 此處很有可能會有問題!!
        age = age;   // 此處很有可能會有問題!!
    }
}

 

編譯器很有可能分不清 name 到底是形參還是成員變數,怎麼破? this 關鍵字就可以幫忙解決。

this關鍵字

  • this關鍵字可以出現在成員方法、構造器中,代表當前對象的地址。

  • 作用:訪問當前對象的成員變數、成員方法。

public class Person
{
    private string name;
    private string age;
    public Person(string name,string age)
    {
        this.name = name; 
        this.age = age;
    }
}

10 . 作業

  1. 學生類:

    • 欄位:姓名,性別,成績,零錢

    • 屬性:姓名:性別,成績( 只寫Set訪問器),成績等級(成績<60 -->差,60<= 成績<= 70 ---> 一般,70< 成績<=80 --->中,80<成績 <=90--->良, 其他---->優, 並且此屬性只讀),零錢

    • 重載構造方法,無參,有參(姓名,性別,成績,零錢)

  2. 學生類中定義Print 方法,將 姓名,性別,成績,零錢等級 輸出到控制台。

  3. 在學生類中,定義HelpShop()方法,意思是 學生可以幫其他同學購物,然後自己獲得同學給的1元的佣金。偽代碼如下:

    public class Student
    {
        // ...欄位
        // ...屬性
        
        /// <summary>
        /// 幫其他同學購物
        /// <summary>
        /// <param name="s">被幫助的同學</param>
        /// <param name="money">購物所花費的金額</param>
        public void HelpShop(Student s, decimal money)
        {
            
        }
    }
  4. 在Main方法中創建學生類對象,通過無參構造方法創建 s1 對象,然後給 姓名,性別,成績,零錢 屬性賦值。

  5. 在Main方法中創建學生類對象,通過有參構造方法創建 s2 對象 並初始化對象。

  6. 調用s1, s2 Print方法,查看屬性值。

  7. s1 調用 HelpShop 方法, 將 s2 作為參數傳遞進去

  8. 再次調用Print 方法,查看s1, s2 的屬性值的變化。

       

視頻教程:

譽尚學教育_譽尚學教育騰訊課堂官網 (qq.com)
或者:
C# 最強入門編程(.Net 學習系列開山巨作)_嗶哩嗶哩_bilibili

 

海闊平魚躍,天高任我行,給我一片藍天,讓我自由翱翔。
您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 如前所述,在前幾章內容中筆者簡單介紹了`記憶體讀寫`的基本實現方式,這其中包括了`CR3切換`讀寫,`MDL映射`讀寫,`記憶體拷貝`讀寫,本章將在如前所述的讀寫函數進一步封裝,並以此來實現驅動讀寫記憶體浮點數的目的。記憶體`浮點數`的讀寫依賴於`讀寫記憶體位元組`的實現,因為浮點數本質上也可以看作是一個位元組集... ...
  • # 還在愁個人博客沒有圖片放?🥱 # 前言 之前將爬取的圖片下載後,我也是放到我了我的博客上面 [ZY知識庫 · ZY - Home Page (pljzy.top)](https://pljzy.top/) 然後順便寫了一個隨機返回圖片的介面,現在我就來說一下如何使用這個介面,以便在自己的博客上 ...
  • 在 WPF 中,CanContentScroll 是 ScrollViewer 控制項的一個附加屬性,它控制滾動視圖中的內容是否按項或像素來滾動。 當 CanContentScroll 設置為 false 時,表示 ScrollViewer 控制項使用逐像素的滾動方式,這意味著滾動視圖中的內容會以像素為 ...
  • 1. 泛型 泛指某種類型。 1、使用參數形式定義 2、使用時傳入具體類型 3、編譯時檢查類型安全 4、邏輯上是多個不同類型 泛型與非泛型之間的區別 性能高:可以避免裝箱和拆箱操作 類型安全 :在進行類型轉換的時候不會拋出異常 代碼重用:定義一次,用許多種不同類型實例化 代碼擴展性好 ArrayLis ...
  • 編寫包含多個 `csproj` 的程式時,隨著項目數量的持續增加,可能涉及一些文件夾的變動,手動添加項目或者變動會變得非常麻煩,這個時候,可以利用 `dotnet cli` 幫助我們完成。 如果從零開始,我們可以新建一個解決方案。 ```powershell dotnet new sln -n to ...
  • # 依賴註入的使用 ## 構造方法註入 這是將服務註入類的最常用方法,是將依賴項註入類的首選方式,也是微軟推崇的模式。這樣,除非提供了所有構造方法註入的依賴項,否則無法構造類,顯示的聲明瞭類必需的服務,使開發人員一目瞭然。 ```csharp public class BookAppService ...
  • 假設老師類設計如下: class 老師類 { 屬性:姓名,性別,生日,工資 行為:吃飯,跑步,教學 } 學生類設計如下: class 老師類 { 屬性:姓名,性別,生日,班級 行為:吃飯,跑步,學習 } 我們秉承著,讓最簡潔的代碼,實現最最強大的功能原則,能否讓上述案例中的重覆代碼進行優化呢?我們能 ...
  • 前言 我們天天都在使用 Console.WriteLine("Hello world"); ​ Console.ReadLine(""); ​ Arrays.Sort() 為什麼Console 類 調用 方法不需要實例化而可以直接調用呢? 我們可以查看Console的源碼發現Console類定義如下 ...
一周排行
    -Advertisement-
    Play Games
  • C#TMS系統代碼-基礎頁面BaseCity學習 本人純新手,剛進公司跟領導報道,我說我是java全棧,他問我會不會C#,我說大學學過,他說這個TMS系統就給你來管了。外包已經把代碼給我了,這幾天先把增刪改查的代碼背一下,說不定後面就要趕鴨子上架了 Service頁面 //using => impo ...
  • 委托與事件 委托 委托的定義 委托是C#中的一種類型,用於存儲對方法的引用。它允許將方法作為參數傳遞給其他方法,實現回調、事件處理和動態調用等功能。通俗來講,就是委托包含方法的記憶體地址,方法匹配與委托相同的簽名,因此通過使用正確的參數類型來調用方法。 委托的特性 引用方法:委托允許存儲對方法的引用, ...
  • 前言 這幾天閑來沒事看看ABP vNext的文檔和源碼,關於關於依賴註入(屬性註入)這塊兒產生了興趣。 我們都知道。Volo.ABP 依賴註入容器使用了第三方組件Autofac實現的。有三種註入方式,構造函數註入和方法註入和屬性註入。 ABP的屬性註入原則參考如下: 這時候我就開始疑惑了,因為我知道 ...
  • C#TMS系統代碼-業務頁面ShippingNotice學習 學一個業務頁面,ok,領導開完會就被裁掉了,很突然啊,他收拾東西的時候我還以為他要旅游提前請假了,還在尋思為什麼回家連自己買的幾箱飲料都要叫跑腿帶走,怕被偷嗎?還好我在他開會之前拿了兩瓶芬達 感覺感覺前面的BaseCity差不太多,這邊的 ...
  • 概述:在C#中,通過`Expression`類、`AndAlso`和`OrElse`方法可組合兩個`Expression<Func<T, bool>>`,實現多條件動態查詢。通過創建表達式樹,可輕鬆構建複雜的查詢條件。 在C#中,可以使用AndAlso和OrElse方法組合兩個Expression< ...
  • 閑來無聊在我的Biwen.QuickApi中實現一下極簡的事件匯流排,其實代碼還是蠻簡單的,對於初學者可能有些幫助 就貼出來,有什麼不足的地方也歡迎板磚交流~ 首先定義一個事件約定的空介面 public interface IEvent{} 然後定義事件訂閱者介面 public interface I ...
  • 1. 案例 成某三甲醫預約系統, 該項目在2024年初進行上線測試,在正常運行了兩天後,業務系統報錯:The connection pool has been exhausted, either raise MaxPoolSize (currently 800) or Timeout (curren ...
  • 背景 我們有些工具在 Web 版中已經有了很好的實踐,而在 WPF 中重新開發也是一種費時費力的操作,那麼直接集成則是最省事省力的方法了。 思路解釋 為什麼要使用 WPF?莫問為什麼,老 C# 開發的堅持,另外因為 Windows 上已經裝了 Webview2/edge 整體打包比 electron ...
  • EDP是一套集組織架構,許可權框架【功能許可權,操作許可權,數據訪問許可權,WebApi許可權】,自動化日誌,動態Interface,WebApi管理等基礎功能於一體的,基於.net的企業應用開發框架。通過友好的編碼方式實現數據行、列許可權的管控。 ...
  • .Net8.0 Blazor Hybird 桌面端 (WPF/Winform) 實測可以完整運行在 win7sp1/win10/win11. 如果用其他工具打包,還可以運行在mac/linux下, 傳送門BlazorHybrid 發佈為無依賴包方式 安裝 WebView2Runtime 1.57 M ...