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

来源: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
  • Timer是什麼 Timer 是一種用於創建定期粒度行為的機制。 與標準的 .NET System.Threading.Timer 類相似,Orleans 的 Timer 允許在一段時間後執行特定的操作,或者在特定的時間間隔內重覆執行操作。 它在分散式系統中具有重要作用,特別是在處理需要周期性執行的 ...
  • 前言 相信很多做WPF開發的小伙伴都遇到過表格類的需求,雖然現有的Grid控制項也能實現,但是使用起來的體驗感並不好,比如要實現一個Excel中的表格效果,估計你能想到的第一個方法就是套Border控制項,用這種方法你需要控制每個Border的邊框,並且在一堆Bordr中找到Grid.Row,Grid. ...
  • .NET C#程式啟動閃退,目錄導致的問題 這是第2次踩這個坑了,很小的編程細節,容易忽略,所以寫個博客,分享給大家。 1.第一次坑:是windows 系統把程式運行成服務,找不到配置文件,原因是以服務運行它的工作目錄是在C:\Windows\System32 2.本次坑:WPF桌面程式通過註冊表設 ...
  • 在分散式系統中,數據的持久化是至關重要的一環。 Orleans 7 引入了強大的持久化功能,使得在分散式環境下管理數據變得更加輕鬆和可靠。 本文將介紹什麼是 Orleans 7 的持久化,如何設置它以及相應的代碼示例。 什麼是 Orleans 7 的持久化? Orleans 7 的持久化是指將 Or ...
  • 前言 .NET Feature Management 是一個用於管理應用程式功能的庫,它可以幫助開發人員在應用程式中輕鬆地添加、移除和管理功能。使用 Feature Management,開發人員可以根據不同用戶、環境或其他條件來動態地控制應用程式中的功能。這使得開發人員可以更靈活地管理應用程式的功 ...
  • 在 WPF 應用程式中,拖放操作是實現用戶交互的重要組成部分。通過拖放操作,用戶可以輕鬆地將數據從一個位置移動到另一個位置,或者將控制項從一個容器移動到另一個容器。然而,WPF 中預設的拖放操作可能並不是那麼好用。為瞭解決這個問題,我們可以自定義一個 Panel 來實現更簡單的拖拽操作。 自定義 Pa ...
  • 在實際使用中,由於涉及到不同編程語言之間互相調用,導致C++ 中的OpenCV與C#中的OpenCvSharp 圖像數據在不同編程語言之間難以有效傳遞。在本文中我們將結合OpenCvSharp源碼實現原理,探究兩種數據之間的通信方式。 ...
  • 一、前言 這是一篇搭建許可權管理系統的系列文章。 隨著網路的發展,信息安全對應任何企業來說都越發的重要,而本系列文章將和大家一起一步一步搭建一個全新的許可權管理系統。 說明:由於搭建一個全新的項目過於繁瑣,所有作者將挑選核心代碼和核心思路進行分享。 二、技術選擇 三、開始設計 1、自主搭建vue前端和. ...
  • Csharper中的表達式樹 這節課來瞭解一下表示式樹是什麼? 在C#中,表達式樹是一種數據結構,它可以表示一些代碼塊,如Lambda表達式或查詢表達式。表達式樹使你能夠查看和操作數據,就像你可以查看和操作代碼一樣。它們通常用於創建動態查詢和解析表達式。 一、認識表達式樹 為什麼要這樣說?它和委托有 ...
  • 在使用Django等框架來操作MySQL時,實際上底層還是通過Python來操作的,首先需要安裝一個驅動程式,在Python3中,驅動程式有多種選擇,比如有pymysql以及mysqlclient等。使用pip命令安裝mysqlclient失敗應如何解決? 安裝的python版本說明 機器同時安裝了 ...