C#教程8:面向对象编程【01】
一、OOP面向對象定義
面向對象編程 (OOP) 是一種編程范式,它使用對象及其交互來設計應用程序和計算機程序。
OOP中有一些基本的編程概念:
- Abstraction 抽象
- Polymorphism? 多態
- Encapsulation? ?封裝
- Inheritance? ?繼承
????????抽象是通過建模適合問題的類來簡化復雜的現實。多態性是對不同的數據輸入以不同的方式使用運算符或函數的過程。封裝對其他對象隱藏了一個類的實現細節。繼承是一種使用已經定義的類形成新類的方法。
二、C# 對象
????????對象是 C# OOP 程序的基本構建塊。對象是數據和方法的組合。數據和方法稱為對象的成員。在 OOP 程序中,我們創建對象。這些對象通過方法相互通信。每個對象都可以接收消息、發送消息和處理數據。
????????創建對象有兩個步驟。首先,我們定義一個類。類是對象的模板。它是描述類的對象都共享的狀態和行為的藍圖。一個類可用于創建許多對象。在運行時從一個類創建的對象稱為該特定類的實例。
Program.cs
var b = new Being(); Console.WriteLine(b);class Being {}在我們的第一個示例中,我們創建了一個簡單的對象。
class Being {}這是一個簡單的類定義。模板的主體是空的。它沒有任何數據或方法。
var b = new Being();我們創建了一個存在類的新實例。為此,我們有新的關鍵字。 b 變量是創建對象的句柄。
Console.WriteLine(b);????????我們將對象打印到控制臺以獲取對象的一些基本描述。打印一個對象是什么意思?當我們打印一個對象時,我們實際上調用了它的 ToString 方法。但是我們還沒有定義任何方法。這是因為創建的每個對象都繼承自基礎對象。它具有一些在所有創建的對象之間共享的基本功能。其中之一是 ToString 方法。
$ dotnet run Being三 C# 對象的屬性
????????對象屬性是捆綁在類實例中的數據。對象屬性稱為實例變量或成員字段。實例變量是在類中定義的變量,類中的每個對象都有一個單獨的副本。
Program.cs
var p1 = new Person(); p1.name = "Jane";var p2 = new Person(); p2.name = "Beky";Console.WriteLine(p1.name); Console.WriteLine(p2.name);class Person {public string name; }在上面的 C# 代碼中,我們有一個帶有一個成員字段的 Person 類。
class Person {public string name; }我們聲明一個名稱成員字段。 public 關鍵字指定成員字段可以在類塊之外訪問。
var p1 = new Person(); p1.name = "Jane";我們創建一個 Person 類的實例,并將 name 變量設置為“Jane”。我們使用點運算符來訪問對象的屬性。
var p2 = new Person(); p2.name = "Beky";我們創建 Person 類的另一個實例。在這里,我們將變量設置為“Beky”。
Console.WriteLine(p1.name); Console.WriteLine(p2.name);我們將變量的內容打印到控制臺。
$ dotnet run Jane BekyPerson 類的每個實例都有一個單獨的名稱成員字段副本。
四、C# 的方法
????????方法是定義在類體內的函數。它們用于使用我們對象的屬性執行操作。方法為我們的程序帶來了模塊化。
????????方法在 OOP 范式的封裝概念中是必不可少的。例如,我們的 AccessDatabase 類中可能有一個 Connect 方法。我們不需要知道 Connect 方法是如何連接到數據庫的。我們只需要知道它是用來連接數據庫的。這對于劃分編程職責至關重要,尤其是在大型應用程序中。
????????對象分組狀態和行為,方法代表對象的行為部分。
Program.cs
var c = new Circle(); c.SetRadius(5);Console.WriteLine(c.Area());class Circle {private int radius;public void SetRadius(int radius){this.radius = radius;}public double Area(){return this.radius * this.radius * Math.PI;} }????????在代碼示例中,我們有一個 Circle 類。我們定義了兩種方法。
private int radius;????????我們有一個成員字段。它是圓的半徑。私有關鍵字是訪問說明符。它告訴變量僅限于外部世界。如果我們想從外部修改這個變量,我們必須使用公開可用的 SetRadius 方法。這樣我們就可以保護我們的數據。
public void SetRadius(int radius) {this.radius = radius; }????????這是 SetRadius 方法。 this 變量是一個特殊變量,我們使用它來訪問方法中的成員字段。 this.radius 是一個實例變量,而 radius 是一個局部變量,僅在 SetRadius 方法內有效。
var c = new Circle(); c.SetRadius(5);????????我們創建一個 Circle 類的實例,并通過在圓的對象上調用 SetRadius 方法來設置它的半徑。我們使用點運算符來調用該方法。
public double Area() {return this.radius * this.radius * Math.PI; }Area 方法返回圓的面積。 Math.PI 是一個內置常量。
$ dotnet run 78.5398163397448五、C#?訪問修飾符
????????訪問修飾符設置方法和成員字段的可見性。 C# 有四個基本的訪問修飾符:public、protected、private 和 internal。可以從任何地方訪問公共成員。受保護的成員只能在類本身以及繼承的類和父類中訪問。私有成員僅限于包含類型,例如僅在其類或接口內。可以從同一個程序集(exe 或 DLL)中訪問內部成員。
????????還有兩種修飾符組合:protected internal 和 private protected。受保護的內部類型或成員可以被聲明它的程序集中的任何代碼訪問,也可以從另一個程序集中的派生類中訪問。私有受保護類型或成員只能在其聲明程序集中、通過同一類中的代碼或從該類派生的類型中訪問。
????????訪問修飾符保護數據免受意外修改。它們使程序更加健壯。
| public | + | + | + | + | + |
| protected | + | o | + | + | o |
| internal | + | + | o | o | o |
| private | + | o | o | o | o |
| protected internal | + | + | + | + | o |
| private protected | + | o | o | + | o |
上表總結了 C# 訪問修飾符(+ 可訪問,o 不可訪問)。
Program.cs
var p = new Person(); p.name = "Jane";p.SetAge(17);Console.WriteLine($"{p.name} is {p.GetAge()} years old");class Person {public string name;private int age;public int GetAge(){return this.age;}public void SetAge(int age){this.age = age;} }在上面的程序中,我們有兩個成員字段。一個是公開的,另一個是私有的。
public int GetAge() {return this.age; }????????如果成員字段是私有的,則訪問它的唯一方法是通過方法。如果我們想修改類之外的屬性,則必須將方法聲明為 public。這是數據保護的一個重要方面。
public void SetAge(int age) {this.age = age; }SetAge 方法使我們能夠從類定義之外更改私有年齡變量。
var p = new Person(); p.name = "Jane";????????我們創建一個 Person 類的新實例。因為 name 屬性是公開的,所以我們可以直接訪問它。但是,不建議這樣做。
p.SetAge(17);SetAge 方法修改年齡成員字段。無法直接訪問或修改它,因為它被聲明為私有。
Console.WriteLine($"{p.name} is {p.GetAge()} years old");最后,我們訪問這兩個成員來構建一個字符串。
$ dotnet run Jane is 17 years old具有私有訪問修飾符的成員字段不會被派生類繼承。
Program.cs
var derived = new Derived(); derived.info();class Base {public string name = "Base";protected int id = 5323;private bool isDefined = true; }class Derived : Base {public void info(){Console.WriteLine("This is Derived class");Console.WriteLine("Members inherited");Console.WriteLine(this.name);Console.WriteLine(this.id);// Console.WriteLine(this.isDefined);} }????????在前面的程序中,我們有一個繼承自基類的派生類。基類具有三個成員字段。所有這些都具有不同的訪問修飾符。 isDefined 成員不被繼承。私有修飾符可以防止這種情況。
class Derived : Base????????派生類繼承自基類。要從另一個類繼承,我們使用冒號 (:) 運算符。
Console.WriteLine(this.name); Console.WriteLine(this.id); // Console.WriteLine(this.isDefined);????????公共和受保護的成員由派生類繼承。它們可以被訪問。私有成員不會被繼承。訪問成員字段的行被注釋掉。如果我們取消注釋該行,代碼將無法編譯。
$ dotnet run ... warning CS0414: The field 'Base.isDefined' is assigned but its value is never used ... This is Derived class Members inherited Base 5323六、C# 構造函數
????????構造函數是一種特殊的方法。創建對象時會自動調用它。構造函數不返回值。構造函數的目的是初始化一個對象的狀態。構造函數與類同名。構造函數是方法,所以它們也可以被重載。
????????構造函數不能被繼承。它們按繼承順序調用。如果我們不為類編寫任何構造函數,C# 提供了一個隱式默認構造函數。如果我們提供任何類型的構造函數,則不提供默認值。
Program.cs
new Being(); new Being("Tom");class Being {public Being(){Console.WriteLine("Being is created");}public Being(string being){Console.WriteLine($"Being {being} is created");} }我們有一個存在類。這個類有兩個構造函數。第一個不帶參數;第二個接受一個參數。
public Being(string being) {Console.WriteLine($"Being {being} is created"); }此構造函數采用一個字符串參數。
new Being();創建了一個存在類的實例。這次在對象創建時調用不帶參數的構造函數。
$ dotnet run Being is created Being Tom is created在下一個示例中,我們啟動類的數據成員。變量的初始化是構造函數的典型工作。
Program.cs
var name = "Lenka"; var born = new DateTime(1990, 3, 5);var friend = new MyFriend(name, born); friend.Info();class MyFriend {private DateTime born;private string name;public MyFriend(string name, DateTime born){this.name = name;this.born = born;}public void Info(){Console.WriteLine("{0} was born on {1}",this.name, this.born.ToShortDateString());} }我們有一個帶有數據成員和方法的 MyFriend 類。
private DateTime born; private string name;我們在類定義中有兩個私有變量。
public MyFriend(string name, DateTime born) {this.name = name;this.born = born; }在構造函數中,我們初始化了兩個數據成員。 this 變量是用于引用對象變量的處理程序。
var friend = new MyFriend(name, born); friend.Info();我們創建一個帶有兩個參數的 MyFriend 對象。然后我們調用對象的 Info 方法。
$ dotnet run Lenka was born on 3/5/1990七、C# 構造鏈
????????構造函數鏈接是類從構造函數調用另一個構造函數的能力。要從同一類調用另一個構造函數,我們使用 this 關鍵字。
Program.cs
new Circle(5); new Circle();class Circle {public Circle(int radius){Console.WriteLine($"Circle, r={radius} is created");}public Circle() : this(1) { } }我們有一個 Circle 課程。該類有兩個構造函數。一個帶一個參數,一個不帶任何參數。
public Circle(int radius) {Console.WriteLine("Circle, r={0} is created", radius); }這個構造函數接受一個參數——半徑。
public Circle() : this(1) { }這是沒有參數的構造函數。它只是調用另一個構造函數并給它一個默認的半徑 1。
$ dotnet run Circle, r=5 is created Circle, r=1 is created八、C# ToString 方法
????????每個對象都有一個 ToString 方法。它返回對象的人類可讀表示。默認實現返回對象類型的完全限定名稱。請注意,當我們使用對象作為參數調用 Console.WriteLine 方法時,會調用 ToString。
Program.cs
var b = new Being(); var o = new Object();Console.WriteLine(o.ToString()); Console.WriteLine(b.ToString()); Console.WriteLine(b);class Being {public override string ToString(){return "This is Being class";} }????????我們有一個存在類,我們在其中覆蓋了 ToString 方法的默認實現。
public override string ToString() {return "This is Being class"; }????????創建的每個類都繼承自基礎對象。 ToString 方法屬于該對象類。我們使用覆蓋關鍵字來通知我們正在覆蓋一個方法。
var b = new Being(); var o = new Object();????????我們創建一個自定義對象和一個內置對象。
Console.WriteLine(o.ToString()); Console.WriteLine(b.ToString());????????我們在這兩個對象上調用 ToString 方法。
Console.WriteLine(b);????????正如我們之前指定的,將對象作為參數放置到 Console.WriteLine 將調用其 ToString 方法。這一次,我們隱式調用了該方法。
$ dotnet run System.Object This is Being class This is Being class九、C#對象初始化
????????對象初始化器讓我們在創建時為對象的任何可訪問字段或屬性分配值,而無需調用構造函數。屬性或字段在 {} 括號內分配。此外,我們可以為構造函數指定參數或省略參數。
Program.cs
var u = new User { Name = "John Doe", Occupation = "gardener" }; Console.WriteLine(u);class User {public User() {}public string Name { set; get; }public string Occupation { set; get; }public override string ToString(){return $"{Name} is a {Occupation}";} }在示例中,我們使用對象初始化器語法創建一個新用戶。
public User() {}我們定義了一個空的構造函數。
public string Name { set; get; } public string Occupation { set; get; }我們有兩個屬性:姓名和職業。
var u = new User { Name = "John Doe", Occupation = "gardener" };我們將值分配給 {} 括號中的屬性。
$ dotnet run John Doe is a gardener總結
以上是生活随笔為你收集整理的C#教程8:面向对象编程【01】的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: C#教程7:数组
- 下一篇: C#教程8:面向对象编程【02】