<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                合規國際互聯網加速 OSASE為企業客戶提供高速穩定SD-WAN國際加速解決方案。 廣告
                # C# 面向對象編程 II > 原文: [https://zetcode.com/lang/csharp/oopii/](https://zetcode.com/lang/csharp/oopii/) 在 C# 教程的這一章中,我們將繼續介紹 OOP。 我們介紹了接口,多態,深層和淺層副本,密封類和異常。 ## C# 接口 遙控器是觀眾和電視之間的接口。 它是此電子設備的接口。 外交禮儀指導外交領域的所有活動。 道路規則是駕車者,騎自行車者和行人必須遵守的規則。 編程中的接口類似于前面的示例。 接口是: * API * 合約 對象通過其公開的方法與外界交互。 實際的實現對程序員而言并不重要,或者也可能是秘密的。 公司可能會出售圖書館,但它不想透露實際的實現情況。 程序員可能會在 GUI 工具箱的窗口上調用`Maximize()`方法,但對如何實現此方法一無所知。 從這個角度來看,接口是對象與外界交互的方式,而又不會過多地暴露其內部功能。 從第二個角度來看,接口就是契約。 如果達成協議,則必須遵循。 它們用于設計應用的架構。 他們幫助組織代碼。 接口是完全抽象的類型。 它們使用`interface`關鍵字聲明。 接口只能具有方法,屬性,事件或索引器的簽名。 所有接口成員都隱式具有公共訪問權限。 接口成員不能指定訪問修飾符。 接口不能具有完全實現的方法,也不能具有成員字段。 C# 類可以實現任何數量的接口。 一個接口還可以擴展任何數量的接口。 實現接口的類必須實現接口的所有方法簽名。 接口用于模擬多重繼承。 C# 類只能從一個類繼承,但可以實現多個接口。 使用接口的多重繼承與繼承方法和變量無關。 它是關于繼承想法或合同的,這些想法或合同由接口描述。 接口和抽象類之間有一個重要的區別。 抽象類為繼承層次結構中相關的類提供部分實現。 另一方面,可以通過彼此不相關的類來實現接口。 例如,我們有兩個按鈕。 經典按鈕和圓形按鈕。 兩者都繼承自抽象按鈕類,該類為所有按鈕提供了一些通用功能。 實現類是相關的,因為它們都是按鈕。 另一個示例可能具有類`Database`和`SignIn`。 它們彼此無關。 我們可以應用`ILoggable`接口,該接口將迫使他們創建執行日志記錄的方法。 ## C# 簡單接口 以下程序使用一個簡單的接口。 `Program.cs` ```cs using System; namespace SimpleInterface { interface IInfo { void DoInform(); } class Some : IInfo { public void DoInform() { Console.WriteLine("This is Some Class"); } } class Program { static void Main(string[] args) { var some = new Some(); some.DoInform(); } } } ``` 這是一個演示接口的簡單 C# 程序。 ```cs interface IInfo { void DoInform(); } ``` 這是接口`IInfo`。 它具有`DoInform()`方法簽名。 ```cs class Some : IInfo ``` 我們實現了`IInfo`接口。 為了實現特定的接口,我們使用冒號(:)運算符。 ```cs public void DoInform() { Console.WriteLine("This is Some Class"); } ``` 該類提供了`DoInform()`方法的實現。 ## C# 多個接口 下一個示例顯示了一個類如何實現多個接口。 `Program.cs` ```cs using System; namespace MultipleInterfaces { interface Device { void SwitchOn(); void SwitchOff(); } interface Volume { void VolumeUp(); void VolumeDown(); } interface Pluggable { void PlugIn(); void PlugOff(); } class CellPhone : Device, Volume, Pluggable { public void SwitchOn() { Console.WriteLine("Switching on"); } public void SwitchOff() { Console.WriteLine("Switching on"); } public void VolumeUp() { Console.WriteLine("Volume up"); } public void VolumeDown() { Console.WriteLine("Volume down"); } public void PlugIn() { Console.WriteLine("Plugging In"); } public void PlugOff() { Console.WriteLine("Plugging Off"); } } class Program { static void Main(string[] args) { var cellPhone = new CellPhone(); cellPhone.SwitchOn(); cellPhone.VolumeUp(); cellPhone.PlugIn(); } } } ``` 我們有一個`CellPhone`類,它從三個接口繼承。 ```cs class CellPhone : Device, Volume, Pluggable ``` 該類實現所有三個接口,并用逗號分隔。 `CellPhone`類必須實現來自所有三個接口的所有方法簽名。 ```cs $ dotnet run Switching on Volume up Plugging In ``` 運行程序,我們得到此輸出。 ## C# 多接口繼承 下一個示例顯示接口如何從多個其他接口繼承。 `Program.cs` ```cs using System; namespace InterfaceInheritance { interface IInfo { void DoInform(); } interface IVersion { void GetVersion(); } interface ILog : IInfo, IVersion { void DoLog(); } class DBConnect : ILog { public void DoInform() { Console.WriteLine("This is DBConnect class"); } public void GetVersion() { Console.WriteLine("Version 1.02"); } public void DoLog() { Console.WriteLine("Logging"); } public void Connect() { Console.WriteLine("Connecting to the database"); } } class Program { static void Main(string[] args) { var db = new DBConnect(); db.DoInform(); db.GetVersion(); db.DoLog(); db.Connect(); } } } ``` 我們定義了三個接口。 我們可以按層次結構組織接口。 ```cs interface ILog : IInfo, IVersion ``` `ILog`接口繼承自其他兩個接口。 ```cs public void DoInform() { Console.WriteLine("This is DBConnect class"); } ``` `DBConnect`類實現`DoInform()`方法。 該方法由該類實現的`ILog`接口繼承。 ```cs $ dotnet run This is DBConnect class Version 1.02 Logging Connecting to the database ``` 這是輸出。 ## C# 多態 多態是以不同方式將運算符或函數用于不同數據輸入的過程。 實際上,多態意味著如果類 B 從類 A 繼承,那么它不必繼承關于類 A 的所有內容。 它可以完成 A 類所做的某些事情。 通常,多態是以不同形式出現的能力。 從技術上講,它是重新定義派生類的方法的能力。 多態與將特定實現應用于接口或更通用的基類有關。 多態是重新定義派生類的方法的能力。 `Program.cs` ```cs using System; namespace Polymorphism { abstract class Shape { protected int x; protected int y; public abstract int Area(); } class Rectangle : Shape { public Rectangle(int x, int y) { this.x = x; this.y = y; } public override int Area() { return this.x * this.y; } } class Square : Shape { public Square(int x) { this.x = x; } public override int Area() { return this.x * this.x; } } class Program { static void Main(string[] args) { Shape[] shapes = { new Square(5), new Rectangle(9, 4), new Square(12) }; foreach (Shape shape in shapes) { Console.WriteLine(shape.Area()); } } } } ``` 在上面的程序中,我們有一個抽象的`Shape`類。 此類演變為兩個后代類別:`Rectangle`和`Square`。 兩者都提供了自己的`Area()`方法實現。 多態為 OOP 系統帶來了靈活性和可伸縮性。 ```cs public override int Area() { return this.x * this.y; } ... public override int Area() { return this.x * this.x; } ``` `Rectangle`和`Square`類具有`Area()`方法的自己的實現。 ```cs Shape[] shapes = { new Square(5), new Rectangle(9, 4), new Square(12) }; ``` 我們創建三個形狀的數組。 ```cs foreach (Shape shape in shapes) { Console.WriteLine(shape.Area()); } ``` 我們遍歷每個形狀,并在其上調用`Area()`方法。 編譯器為每種形狀調用正確的方法。 這就是多態的本質。 ## C# 密封類 `sealed`關鍵字用于防止意外地從類派生。 密封類不能是抽象類。 `Program.cs` ```cs using System; namespace DerivedMath { sealed class Math { public static double GetPI() { return 3.141592; } } class Derived : Math { public void Say() { Console.WriteLine("Derived class"); } } class Program { static void Main(string[] args) { var dm = new Derived(); dm.Say(); } } } ``` 在上面的程序中,我們有一個`Math`基類。 該類的唯一目的是為程序員提供一些有用的方法和常量。 (出于簡單起見,在我們的案例中,我們只有一種方法。)它不是從繼承而創建的。 為了防止不知情的其他程序員從此類中派生,創建者創建了`sealed`類。 如果嘗試編譯該程序,則會出現以下錯誤:'Derived'不能從密封類'Math'派生。 ## C# 深層副本與淺層副本 數據復制是編程中的重要任務。 對象是 OOP 中的復合數據類型。 對象中的成員字段可以按值或按引用存儲。 可以以兩種方式執行復制。 淺表副本將所有值和引用復制到新實例中。 引用所指向的數據不會被復制; 僅指針被復制。 新的引用指向原始對象。 對引用成員的任何更改都會影響兩個對象。 深層副本將所有值復制到新實例中。 如果成員存儲為引用,則深層副本將對正在引用的數據執行深層副本。 創建一個引用對象的新副本。 并存儲指向新創建對象的指針。 對這些引用對象的任何更改都不會影響該對象的其他副本。 深拷貝是完全復制的對象。 如果成員字段是值類型,則將對該字段進行逐位復制。 如果該字段是引用類型,則復制引用,但不是復制引用的對象。 因此,原始對象中的引用和克隆對象中的引用指向同一對象。 (來自 programmingcorner.blogspot.com 的明確解釋) ### C# 淺表復制 以下程序執行淺表復制。 `Program.cs` ```cs using System; namespace ShallowCopy { class Color { public int red; public int green; public int blue; public Color(int red, int green, int blue) { this.red = red; this.green = green; this.blue = blue; } } class MyObject : ICloneable { public int id; public string size; public Color col; public MyObject(int id, string size, Color col) { this.id = id; this.size = size; this.col = col; } public object Clone() { return new MyObject(this.id, this.size, this.col); } public override string ToString() { var s = String.Format("id: {0}, size: {1}, color:({2}, {3}, {4})", this.id, this.size, this.col.red, this.col.green, this.col.blue); return s; } } class Program { static void Main(string[] args) { var col = new Color(23, 42, 223); var obj1 = new MyObject(23, "small", col); var obj2 = (MyObject) obj1.Clone(); obj2.id += 1; obj2.size = "big"; obj2.col.red = 255; Console.WriteLine(obj1); Console.WriteLine(obj2); } } } ``` 這是一個淺表副本的示例。 我們定義了兩個自定義對象:`MyObject`和`Color`。 `MyObject`對象將引用 Color 對象。 ```cs class MyObject : ICloneable ``` 我們應該為要克隆的對象實現`ICloneable`接口。 ```cs public object Clone() { return new MyObject(this.id, this.size, this.col); } ``` `ICloneable`接口迫使我們創建`Clone()`方法。 此方法返回具有復制值的新對象。 ```cs var col = new Color(23, 42, 223); ``` 我們創建`Color`對象的實例。 ```cs var obj1 = new MyObject(23, "small", col); ``` 創建`MyObject`類的實例。 `Color`對象的實例傳遞給構造器。 ```cs var obj2 = (MyObject) obj1.Clone(); ``` 我們創建`obj1`對象的淺表副本,并將其分配給`obj2`變量。 `Clone()`方法返回`Object`,我們期望`MyObject`。 這就是我們進行顯式轉換的原因。 ```cs obj2.id += 1; obj2.size = "big"; obj2.col.red = 255; ``` 在這里,我們修改復制對象的成員字段。 我們增加`id`,將`size`更改為`"big"`,然后更改顏色對象的紅色部分。 ```cs Console.WriteLine(obj1); Console.WriteLine(obj2); ``` `Console.WriteLine()`方法調用`obj2`對象的`ToString()`方法,該方法返回對象的字符串表示形式。 ```cs $ dotnet run id: 23, size: small, color:(255, 42, 223) id: 24, size: big, color:(255, 42, 223) ``` 我們可以看到 ID 是不同的(23 對 24)。 大小不同(`small`與`big`)。 但是,這兩個實例的顏色對象的紅色部分相同(255)。 更改克隆對象的成員值(`id`,`size`)不會影響原始對象。 更改引用對象(`col`)的成員也影響了原始對象。 換句話說,兩個對象都引用內存中的同一顏色對象。 ### C# 深層復制 要更改此行為,我們接下來將做一個深層復制。 `Program.cs` ```cs using System; namespace DeepCopy { class Color : ICloneable { public int red; public int green; public int blue; public Color(int red, int green, int blue) { this.red = red; this.green = green; this.blue = blue; } public object Clone() { return new Color(this.red, this.green, this.blue); } } class MyObject : ICloneable { public int id; public string size; public Color col; public MyObject(int id, string size, Color col) { this.id = id; this.size = size; this.col = col; } public object Clone() { return new MyObject(this.id, this.size, (Color)this.col.Clone()); } public override string ToString() { var s = String.Format("id: {0}, size: {1}, color:({2}, {3}, {4})", this.id, this.size, this.col.red, this.col.green, this.col.blue); return s; } } class Program { static void Main(string[] args) { var col = new Color(23, 42, 223); var obj1 = new MyObject(23, "small", col); var obj2 = (MyObject) obj1.Clone(); obj2.id += 1; obj2.size = "big"; obj2.col.red = 255; Console.WriteLine(obj1); Console.WriteLine(obj2); } } } ``` 在此程序中,我們對對象執行深層復制。 ```cs class Color : ICloneable ``` 現在,`Color`類實現了`ICloneable`接口。 ```cs public object Clone() { return new Color(this.red, this.green, this.blue); } ``` 我們也為`Color`類提供了`Clone()`方法。 這有助于創建引用對象的副本。 ```cs public object Clone() { return new MyObject(this.id, this.size, (Color) this.col.Clone()); } ``` 當我們克隆`MyObject`時,我們根據`col`引用類型調用`Clone()`方法。 這樣,我們也可以獲得顏色值的副本。 ```cs $ dotnet run id: 23, size: small, color:(23, 42, 223) id: 24, size: big, color:(255, 42, 223) ``` 現在,所引用的`Color`對象的紅色部分不再相同。 原始對象保留了其先前的值(23)。 ## C# 異常 異常是為處理異常的發生而設計的,這些特殊情況會改變程序執行的正常流程。 引發或引發異常。 在執行應用期間,許多事情可能出錯。 磁盤可能已滿,我們無法保存文件。 當我們的應用嘗試連接到站點時,互聯網連接可能會斷開。 所有這些都可能導致我們的應用崩潰。 程序員有責任處理可以預期的錯誤。 `try`,`catch`和`finally`關鍵字用于處理異常。 `Program.cs` ```cs using System; namespace DivisionByZero { class Program { static void Main(string[] args) { int x = 100; int y = 0; int z; try { z = x / y; } catch (ArithmeticException e) { Console.WriteLine("An exception occurred"); Console.WriteLine(e.Message); } } } } ``` 在上面的程序中,我們有意將數字除以零。 這會導致錯誤。 ```cs try { z = x / y; } ``` 容易出錯的語句放置在`try`塊中。 ```cs catch (ArithmeticException e) { Console.WriteLine("An exception occurred"); Console.WriteLine(e.Message); } ``` 異常類型跟隨`catch`關鍵字。 在我們的情況下,我們有一個`ArithmeticException`。 由于算術,轉換或轉換操作中的錯誤而引發此異常。 發生錯誤時,將執行`catch`關鍵字之后的語句。 發生異常時,將創建一個異常對象。 從該對象中,我們獲得`Message`屬性并將其打印到控制臺。 ```cs $ dotnet run An exception occurred Attempted to divide by zero. ``` 代碼示例的輸出。 ### C# 未捕獲的異常 當前上下文中任何未捕獲的異常都會傳播到更高的上下文,并尋找適當的`catch`塊來處理它。 如果找不到任何合適的`catch`塊,則 .NET 運行時的默認機制將終止整個程序的執行。 `Program.cs` ```cs using System; namespace UcaughtException { class Program { static void Main(string[] args) { int x = 100; int y = 0; int z = x / y; Console.WriteLine(z); } } } ``` 在此程序中,我們除以零。 沒有自定義異常處理。 ```cs $ dotnet run Unhandled Exception: System.DivideByZeroException: Division by zero at UncaughtException.Main () [0x00000] ``` C# 編譯器給出了以上錯誤消息。 ### C# `IOException` 發生 I/O 錯誤時,將拋出`IOException`。 在下面的示例中,我們讀取文件的內容。 `Program.cs` ```cs using System; using System.IO; namespace ReadFile { class Program { static void Main(string[] args) { var fs = new FileStream("langs.txt", FileMode.OpenOrCreate); try { var sr = new StreamReader(fs); string line; while ((line = sr.ReadLine()) != null) { Console.WriteLine(line); } } catch (IOException e) { Console.WriteLine("IO Error"); Console.WriteLine(e.Message); } finally { Console.WriteLine("Inside finally block"); if (fs != null) { fs.Close(); } } } } } ``` 始終執行`finally`關鍵字之后的語句。 它通常用于清理任務,例如關閉文件或清除緩沖區。 ```cs } catch (IOException e) { Console.WriteLine("IO Error"); Console.WriteLine(e.Message); } ``` 在這種情況下,我們捕獲了特定的`IOException`異常。 ```cs } finally { Console.WriteLine("Inside finally block"); if (fs != null) { fs.Close(); } } ``` 這些行確保關閉文件處理器。 ```cs $ cat langs.txt C# Java Python Ruby PHP JavaScript ``` 這些是`langs.txt`文件的內容。 ```cs $ dotnet run C# Java Python Ruby PHP JavaScript Inside finally block ``` 這是程序的輸出。 我們使用`cat`命令和程序輸出顯示`langs`文件的內容。 ### C# 多個異常 我們經常需要處理多個異常。 `Program.cs` ```cs using System; using System.IO; namespace MultipleExceptions { class Program { static void Main(string[] args) { int x; int y; double z; try { Console.Write("Enter first number: "); x = Convert.ToInt32(Console.ReadLine()); Console.Write("Enter second number: "); y = Convert.ToInt32(Console.ReadLine()); z = x / y; Console.WriteLine("Result: {0:N} / {1:N} = {2:N}", x, y, z); } catch (DivideByZeroException e) { Console.WriteLine("Cannot divide by zero"); Console.WriteLine(e.Message); } catch (FormatException e) { Console.WriteLine("Wrong format of number."); Console.WriteLine(e.Message); } } } } ``` 在此示例中,我們捕獲了各種異常。 請注意,更具體的異常應先于一般的異常。 我們從控制臺讀取兩個數字,并檢查零除錯誤和數字格式錯誤。 ```cs $ dotnet run Enter first number: we Wrong format of number. Input string was not in a correct format. ``` 運行示例,我們得到了這個結果。 ### C# 自定義異常 定制異常是從`System.Exception`類派生的用戶定義的異常類。 `Program.cs` ```cs using System; namespace CustomException { class BigValueException : Exception { public BigValueException(string msg) : base(msg) { } } class Program { static void Main(string[] args) { int x = 340004; const int LIMIT = 333; try { if (x > LIMIT) { throw new BigValueException("Exceeded the maximum value"); } } catch (BigValueException e) { Console.WriteLine(e.Message); } } } } ``` 我們假定存在無法處理大量數字的情況。 ```cs class BigValueException : Exception ``` 我們有一個`BigValueException`類。 該類派生自內置的`Exception`類。 ```cs const int LIMIT = 333; ``` 大于此常數的數字在我們的程序中被視為`big`。 ```cs public BigValueException(string msg) : base(msg) {} ``` 在構造器內部,我們稱為父級的構造器。 我們將消息傳遞給父級。 ```cs if (x > LIMIT) { throw new BigValueException("Exceeded the maximum value"); } ``` 如果該值大于限制,則拋出自定義異常。 我們給異常消息`Exceeded the maximum value`。 ```cs } catch (BigValueException e) { Console.WriteLine(e.Message); } ``` 我們捕獲到異常并將其消息打印到控制臺。 ```cs $ dotnet run Exceeded the maximum value ``` This is the output of the program. 在 C# 教程的這一部分中,我們繼續討論 C# 中的面向對象編程。
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看