C# 基礎知識系列- 4 面向對象

来源:https://www.cnblogs.com/c7jie/archive/2020/03/29/12593422.html
-Advertisement-
Play Games

面向對象 面向對象是一個抽象的概念,其本質就是對事物以抽象的方式建立對應的模型。 簡單來講,比如我有一隻鋼筆,那麼我就可以通過分析,可以得到 這隻鋼筆的材第是塑料,品牌是個雜牌 ,裡面裝的墨是黑色的,可以用。這時候就能建立一個鋼筆的模型,它在這裡應該有這些屬性: 圖是一個不正確的UML類圖,但是可以 ...


面向對象

面向對象是一個抽象的概念,其本質就是對事物以抽象的方式建立對應的模型。
簡單來講,比如我有一隻鋼筆,那麼我就可以通過分析,可以得到 這隻鋼筆的材第是塑料,品牌是個雜牌 ,裡面裝的墨是黑色的,可以用。這時候就能建立一個鋼筆的模型,它在這裡應該有這些屬性:

file

圖是一個不正確的UML類圖,但是可以簡單的概述一下我們抽象的結果。這個圖就描述了一個我們抽象出來的鋼筆類應該有哪些特性,而我手裡的那隻鋼筆就可以看做是鋼筆類的一個實例。
簡單來講,面向對象編程就是針對一個事件或者說一個過程,找到這個過程中參與的所有人、事務或者相對獨立的個體,按照他們在這個過程中表現,提取出他們的特性,描述他們的行為,然後按照類別不同再抽象出類來。
所以,類是事物的概念抽象,事物是類的特殊實例。

創建一個類

上面簡單的介紹了面向對象的概念,現在先創建一個C#類,然後介紹一下這個類需要註意的地方:

public class Person
{
	private static int count;

	public static int Count
	{
		get { return count; }
		set { count = value; }
	}

	private string name;

	public string Name
	{
		get { return name; }
		set { name = value; }
	}
	public Person()
	{
		Name = "";
		Count = Count + 1;
	}

	public Person(string name)
	{
		this.Name = name;
	}

	public void SayHello()
	{
	}
}

其中:
private string name;private static int count;這兩個在C#中稱為Field,也就是欄位的意思;
public static int Countpublic string Name 這兩個在C#中稱為Property,也就是屬性的意思。
當然,不是說一個是private就叫欄位,另一個是public就稱之為屬性,而是因為屬性有getset來控制訪問和賦值的行為。

public Person()public Person(string name)是構造方法,所謂的構造方法就是初始化一個實例的方法,調用形式如下:
Person p = new Person() 通過new關鍵字+類名+對應的參數列表即可。構造方法沒有返回類型,方法名必須是類名,可以有任意個參數。

面向對象的三大特性

面向對象的三大特性是封裝、繼承、多態。我把它們稱為面向對象面試三巨頭,因為一旦面試,如果有面向對象的問題絕對會問到這三個特性。這裡先簡單介紹一下三大特性,

  • 封裝:對象的方法實現對外是隱藏的,就像我們在不拆開鋼筆之前很難知道鋼筆的墨水是怎麼流動然後寫出字的;
  • 繼承:子類天然擁有父類的屬性和方法,假如我們還有一隻特種鋼筆,那麼我們可以把這隻特種鋼筆抽象出的類認為是鋼筆的子類,這隻特種鋼筆跟鋼筆一樣,可以用來做鋼筆能做的事,雖然有時候不好用;
  • 多態:簡單來講就是多種狀態,對於面向對象來說,就是方法重寫和方法重載。比如說,我們去找領導簽字,領導在忙讓我們把文件放那邊,過一會領導派人送過來簽好字的文件。如果領導有多只鋼筆,那麼領導用哪只筆、在什麼時候、用什麼姿勢對於我們來說就是不確定的狀態,這就是多態的一種。

訪問控制符

在將三大特性之前,先介紹一下 C#的訪問控制。C#常用的訪問控制分為四種:

  • private: 限定只有同屬於一個類的成員才可以訪問,如果限定一個類是私有類,那麼這個類必須是內部類
  • protected: 限定當前類的成員、子類可以訪問,不能用來限定外部類,同private一樣,如果限定類是受保護類,這個類必須是內部類
  • internal(default):預設訪問許可權,對於類和方法來說,限定同一個DLL可以訪問,其他DLL不能訪問。區別是類的 internal 關鍵字可以省略,方法如果省略訪問許可權符,則預設是protected
  • public:公開,所有能引用類的地方都能訪問類里的public對象,這是最開放的許可權。

C#還有更多的訪問控制,不過常用的只有這四種,更多的可以參照【官方文檔】。

封裝

封裝簡單來講就是調用方不知道被調用方的具體實現以及內部機制,就像我們看別人只能看到外表缺看不到器官的運作(當然除非你是醫生)。
那麼封裝有什麼好處呢:

  • 對外隱藏實現,防止外部篡改引發安全問題
  • 減少不必要的關聯,被調用方需要調用方提供參數,但除此之外調用方只需要靜待被調用方返回結果就行
  • 打包一系列的操作,防止中間發生變故

比如說一個鐘錶,給我們一堆零件,在沒有拼接、安裝好之前也就是封裝好,這個鐘錶是不能正常使用的。只有我們按照一定邏輯,將零件安裝好之後(封裝),再裝上電池或上發條(調用) 鐘錶才會轉起來。
簡單的用代碼介紹一下:

class Program
{
	static void Main(string[] args)
	{
		Person p = new Person();
		p.SayHello();
	}
}


public class Person
{
	private static int count;

	public static int Count
	{
		get { return count; }
		set { count = value; }
	}

	private string name;

	public string Name
	{
		get { return name; }
		set { name = value; }
	}

	public Person()
	{
		Name = "小明";
		Count = Count + 1;
	}

	public Person(string name)
	{
	}

	public void SayHello()
	{
		Console.WriteLine("你好,我叫"+Name);
	}
}

簡單看一下,對於Program類來講,Person的SayHello是怎麼實現的完全不知情。這就是封裝的意義。

繼承

C#的繼承是單繼承,也就是說一個類只有一個父類,如果不指明父類,那麼它的父類就是object。換句話說,object是C#繼承體系裡的根,也就是所有類的祖先類。
C#的繼承用 表示,即 class B: A表示B繼承A。

public class A
{
	public virtual void Say()
	{
	}
	public void Look()
	{
	}
}
public class B : A
{
	public override void Say()
	{
	}
}

上述代碼建立了一個簡單的繼承體系。那麼問題來了,繼承有什麼用呢?簡單來講,對於A和B在Say方法有不同的實現,對於調用方來講,它們的表現應當是一致的。換句話說,就是所有用到A的地方,都能用B來代替,這不會出現任何問題。
繼承可以簡化很多行為(方法)一致的寫法。如示例所述,B類在Look上與其父類A類有著一致的行為和表現,那麼B就可以省略了Look的定義和描述,沿用父類的方法。通過繼承可以很快地建立一套豐富的方法體系。子類每一次對父類的方法補充都會在子類里體現出來。所以繼承可以說是面向對象的核心體系。

有個關鍵字需要額外的講解一下saled,如果看到一個類有這個標記,那麼需要註意了,這個類是不可被繼承的類。

多態

多態的實現就是通過類的繼承和方法的重載實現的。類的繼承主要通過重寫父類方法或者覆蓋父類方法來實現的,主要關鍵字就是 virtualoverridenew
具體的介紹是:

  • virtual 關鍵字聲明函數為虛函數,意思就是子類可能會重寫該方法
  • override 用在子類,用來聲明該方法是重寫父類的方法
  • new 跟實例化對象的new不同,這個放在方法前的意思是該方法會隱藏父類方法的實現。
public class A
{
	public virtual void Say()
	{
		//省略實現
	}

	public void SetName()
	{
		//省略實現
	}
}

public sealed class B:A
{
	public override void Say() //重寫父類方法
	{
		//省略實現
	}
	public new void SetName() // 覆蓋父類方法
	{
		//省略實現
	}
}

重寫和覆蓋的區別在哪呢:

A a = new B();
a.Say();// 調用的是 B中 Say方法
a.SetName();//調用的是A的SetName 方法
B b = (B)a;
b.SetName();//調用的是B的SetName 方法
b.Say();// 調用的是 B中 Say方法

類和介面

C#中類和介面的聲明方式不同,類用的關鍵字是class,介面用的是interface。而且類是繼承,介面是實現,一個類只能有一個父類,介面可以有多個。
介面需要註意的地方就死,介面所有的方法都是public的,因為介面就是用來定義規範的,所以一旦它的方法訪問控制不是public的話,就沒什麼意義。

public class Demo1
{
}
public interface IDemo
{
	string Method();
}
public class Demo3 : Demo1, IDemo
{
	public string Method()
	{
		return "test";
	}
	string IDemo.Method()
	{
		return "test2";
	}
}

介面的實現和類的繼承都是 : ,先繼承後實現。

觀察示例代碼,發現Demo3有兩個方法public string Method()string IDemo.Method() 。這兩個都是實現介面的方法,不同的地方是它們的使用:

IDemo idemo = new Demo3();
idemo.Method();//返回 test2
Demo3 demo = new Demo3();
demo.Method();// 返回 test

使用介面名.方法名實現方法的時候,這個方法對於實現類構造的對象來說是不可訪問的。當然兩種方法可以共存,但是不會兩個方法都被認為是介面的實現方法。介面優先使用介面名.方法名 作為實現方法,如果沒找到則認為同名同參的方法為實現方法。

Object 類 常用方法

object 作為基類定義了四個基本方法,這四個方法是所有子類都有的方法,也是一個核心方法:

  • Equals(object obj) 這是一個很重要的方法,它是 C#中判斷兩個對象是否相等的依據,也就是 == 運算符的結果,如果不重寫這個方法的話,返回的結果是兩個對象是否指向同一個引用地址。
  • GetType() 返回這個對象的類型,這是反射機制中重要的一塊
  • ToString() 返回字元串,獲得一個對象的文字描述,預設返回的是對象的地址描述信息,這個方法建議重寫
  • GetHashCode() 返回 Hash值,某些集合和程式機制會以HashCode作為元素的相等性判斷依據,所以在重寫 Equals 之後也要重寫 這個方法,並保證兩個方法對於相同的對象做相等性結果判定是應該表現一致。

擴展方法

C# 有一個很重要的機制就是擴展方法,擴展方法表現出的跟類自有的方法調用結果一致。
具體寫法如下:

public static class Methods
{
	public static string Test(this Person person)
	{
			return "test";
	}
}

需要註意的是,擴展方法所在類必須是靜態類,擴展方法必須是靜態方法,擴展方法第一個參數就是擴展的元素對象,用this標記。

不過很多人對擴展方法褒貶不一,有人認為擴展方法極易破壞繼承鏈,導致一些不必要的麻煩;有人認為擴展方法就跟工具方法一樣,而且可以優化調用方式,統一使用風格。

不過我看來,擴展方法利大於弊。因為擴展方法可以在不修改原有類的基礎上增加功能,同時它也是一個工具類,跟普通的方法是一致的。

更多內容煩請關註我的博客

file


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • Druid簡介 Druid是阿裡開源的資料庫連接池,作為後起之秀,性能比dbcp、c3p0更高,使用也越來越廣泛。 druid的優點 高性能。性能比dbcp、c3p0高很多。 只要是jdbc支持的資料庫,druid都支持,對資料庫的支持性好。並且Druid針對oracle、mysql做了特別優化。 ...
  • public static <T> T map2Object(Map<String, Object> map, Class<T> clazz) { SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); if (map ...
  • A - Coffee 題意:給你一個字元串,要你判斷是否滿足一下條件,全部滿足則輸出“Yes”,否則輸出“No”。 (1)字元串的第3個字母等於字元串的第4個字母 (2)字元串的第5個字母等於字元串的第6個字母 (3)字元串的長度為6,且全部為小寫字母 題解:簽到題,易解 代碼: #include< ...
  • 一、背景 一方面,有時必須從幾個類中派生出一個子類,繼承它們所有的屬性和方法。但是,Java不支持多重繼承。有了介面,就可以得到多重繼承的效果。 另一方面,有時必須從幾個類中抽取出一些共同的行為特征,而它們之間又沒有is-a的關係,僅僅是具有相同的行為特征而已。 二、圖示 三、介面的使用 1.介面: ...
  • 隨著繼承層次中一個個新子類的定義,類變得越來越具體,而父類則更一般,更通用。類的設計應該保證父類和子類能夠共用特征。有時將一個父類設計得非常抽象,以至於它沒有具體的實例,這樣的類叫做抽象類。 舉例: public class test { public static void main(String ...
  • 發現按照教程操作破解Eplan,破解一直不成功。主要原因是MultiKey64在win10上運行不成功。可以通過設備管理看到是否有下圖的驅動 需要關閉win10的簽名認證,這個鏈接就是關閉的方法https://jingyan.baidu.com/article/624e74594dbc8d34e8b ...
  • 你需要瞭解的 HTTP Status Code Intro 現在前後端分離的開發模式越來越流行,後端負責開發對應的 API,前端只需要 關註前端頁面的數據展示和前端邏輯即可。 對於前後端分離這種開發模式,我個人還是比較喜歡的,因為這樣可以讓更專業的人做更專業的事情,後端專註於做 API 的開發設計, ...
  • 在ASP.NET MVC中有四種過濾器類型 Action 1、在ASP.NET MVC項目中,新建文件夾Filter,然後新建類MyCustormFilter,繼承自ActionFilterAttribute類,我們來看下ActionFilterAttribute類有如下四個方法,從命名我應該就可以 ...
一周排行
    -Advertisement-
    Play Games
  • 概述:在C#中,++i和i++都是自增運算符,其中++i先增加值再返回,而i++先返回值再增加。應用場景根據需求選擇,首碼適合先增後用,尾碼適合先用後增。詳細示例提供清晰的代碼演示這兩者的操作時機和實際應用。 在C#中,++i 和 i++ 都是自增運算符,但它們在操作上有細微的差異,主要體現在操作的 ...
  • 上次發佈了:Taurus.MVC 性能壓力測試(ap 壓測 和 linux 下wrk 壓測):.NET Core 版本,今天計劃準備壓測一下 .NET 版本,來測試並記錄一下 Taurus.MVC 框架在 .NET 版本的性能,以便後續持續優化改進。 為了方便對比,本文章的電腦環境和測試思路,儘量和... ...
  • .NET WebAPI作為一種構建RESTful服務的強大工具,為開發者提供了便捷的方式來定義、處理HTTP請求並返迴響應。在設計API介面時,正確地接收和解析客戶端發送的數據至關重要。.NET WebAPI提供了一系列特性,如[FromRoute]、[FromQuery]和[FromBody],用 ...
  • 原因:我之所以想做這個項目,是因為在之前查找關於C#/WPF相關資料時,我發現講解圖像濾鏡的資源非常稀缺。此外,我註意到許多現有的開源庫主要基於CPU進行圖像渲染。這種方式在處理大量圖像時,會導致CPU的渲染負擔過重。因此,我將在下文中介紹如何通過GPU渲染來有效實現圖像的各種濾鏡效果。 生成的效果 ...
  • 引言 上一章我們介紹了在xUnit單元測試中用xUnit.DependencyInject來使用依賴註入,上一章我們的Sample.Repository倉儲層有一個批量註入的介面沒有做單元測試,今天用這個示例來演示一下如何用Bogus創建模擬數據 ,和 EFCore 的種子數據生成 Bogus 的優 ...
  • 一、前言 在自己的項目中,涉及到實時心率曲線的繪製,項目上的曲線繪製,一般很難找到能直接用的第三方庫,而且有些還是定製化的功能,所以還是自己繪製比較方便。很多人一聽到自己畫就害怕,感覺很難,今天就分享一個完整的實時心率數據繪製心率曲線圖的例子;之前的博客也分享給DrawingVisual繪製曲線的方 ...
  • 如果你在自定義的 Main 方法中直接使用 App 類並啟動應用程式,但發現 App.xaml 中定義的資源沒有被正確載入,那麼問題可能在於如何正確配置 App.xaml 與你的 App 類的交互。 確保 App.xaml 文件中的 x:Class 屬性正確指向你的 App 類。這樣,當你創建 Ap ...
  • 一:背景 1. 講故事 上個月有個朋友在微信上找到我,說他們的軟體在客戶那邊隔幾天就要崩潰一次,一直都沒有找到原因,讓我幫忙看下怎麼回事,確實工控類的軟體環境複雜難搞,朋友手上有一個崩潰的dump,剛好丟給我來分析一下。 二:WinDbg分析 1. 程式為什麼會崩潰 windbg 有一個厲害之處在於 ...
  • 前言 .NET生態中有許多依賴註入容器。在大多數情況下,微軟提供的內置容器在易用性和性能方面都非常優秀。外加ASP.NET Core預設使用內置容器,使用很方便。 但是筆者在使用中一直有一個頭疼的問題:服務工廠無法提供請求的服務類型相關的信息。這在一般情況下並沒有影響,但是內置容器支持註冊開放泛型服 ...
  • 一、前言 在項目開發過程中,DataGrid是經常使用到的一個數據展示控制項,而通常表格的最後一列是作為操作列存在,比如會有編輯、刪除等功能按鈕。但WPF的原始DataGrid中,預設只支持固定左側列,這跟大家習慣性操作列放最後不符,今天就來介紹一種簡單的方式實現固定右側列。(這裡的實現方式參考的大佬 ...