c#基础知识梳理(四)
上期回顧 -?https://www.cnblogs.com/liu-jinxin/p/10826971.html?
一、類
當(dāng)你定義一個(gè)類時(shí),你定義了一個(gè)數(shù)據(jù)類型的藍(lán)圖。這實(shí)際上并沒(méi)有定義任何的數(shù)據(jù),但它定義了類的名稱意味著什么,也就是說(shuō),類的對(duì)象由什么組成及在這個(gè)對(duì)象上可執(zhí)行什么操作。對(duì)象是類的實(shí)例。構(gòu)成類的方法和變量成為類的成員。
代碼示例:
1 using System; 2 namespace BoxApplication 3 { 4 class Box 5 { 6 public double length; // 長(zhǎng)度 7 public double breadth; // 寬度 8 public double height; // 高度 9 } 10 class Boxtester 11 { 12 static void Main(string[] args) 13 { 14 Box Box1 = new Box(); // 聲明 Box1,類型為 Box 15 Box Box2 = new Box(); // 聲明 Box2,類型為 Box 16 double volume = 0.0; // 體積 17 18 // Box1 詳述 19 Box1.height = 5.0; 20 Box1.length = 6.0; 21 Box1.breadth = 7.0; 22 23 // Box2 詳述 24 Box2.height = 10.0; 25 Box2.length = 12.0; 26 Box2.breadth = 13.0; 27 28 // Box1 的體積 29 volume = Box1.height * Box1.length * Box1.breadth; 30 Console.WriteLine("Box1 的體積: {0}", volume); 31 32 // Box2 的體積 33 volume = Box2.height * Box2.length * Box2.breadth; 34 Console.WriteLine("Box2 的體積: {0}", volume); 35 Console.ReadKey(); 36 } 37 } 38 } 39 //執(zhí)行結(jié)果 40 //Box1 的體積: 210 41 //Box2 的體積: 1560 View Code(一)、成員函數(shù)
類的成員函數(shù)是一個(gè)在類定義中有它的定義或原型的函數(shù),就像其他變量一樣。作為類的一個(gè)成員,它能在類的任何對(duì)象上操作,且能訪問(wèn)該對(duì)象的類的所有成員。
成員變量是對(duì)象的屬性(從設(shè)計(jì)角度),且它們保持私有來(lái)實(shí)現(xiàn)封裝。這些變量只能使用公共成員函數(shù)來(lái)訪問(wèn)。
代碼示例:
1 using System; 2 namespace BoxApplication 3 { 4 class Box 5 { 6 private double length; // 長(zhǎng)度 7 private double breadth; // 寬度 8 private double height; // 高度 9 public void setLength( double len ) 10 { 11 length = len; 12 } 13 14 public void setBreadth( double bre ) 15 { 16 breadth = bre; 17 } 18 19 public void setHeight( double hei ) 20 { 21 height = hei; 22 } 23 public double getVolume() 24 { 25 return length * breadth * height; 26 } 27 } 28 class Boxtester 29 { 30 static void Main(string[] args) 31 { 32 Box Box1 = new Box(); // 聲明 Box1,類型為 Box 33 Box Box2 = new Box(); // 聲明 Box2,類型為 Box 34 double volume; // 體積 35 36 37 // Box1 詳述 38 Box1.setLength(6.0); 39 Box1.setBreadth(7.0); 40 Box1.setHeight(5.0); 41 42 // Box2 詳述 43 Box2.setLength(12.0); 44 Box2.setBreadth(13.0); 45 Box2.setHeight(10.0); 46 47 // Box1 的體積 48 volume = Box1.getVolume(); 49 Console.WriteLine("Box1 的體積: {0}" ,volume); 50 51 // Box2 的體積 52 volume = Box2.getVolume(); 53 Console.WriteLine("Box2 的體積: {0}", volume); 54 55 Console.ReadKey(); 56 } 57 } 58 } 59 //執(zhí)行結(jié)果 60 //Box1 的體積: 210 61 //Box2 的體積: 1560 View Code(二)、構(gòu)造函數(shù)
類的?構(gòu)造函數(shù)?是類的一個(gè)特殊的成員函數(shù),當(dāng)創(chuàng)建類的新對(duì)象時(shí)執(zhí)行。
構(gòu)造函數(shù)的名稱與類的名稱完全相同,它沒(méi)有任何返回類型。
代碼示例:
1 using System; 2 namespace LineApplication 3 { 4 class Line 5 { 6 private double length; // 線條的長(zhǎng)度 7 public Line() //構(gòu)造函數(shù) 8 { 9 Console.WriteLine("對(duì)象已創(chuàng)建"); 10 } 11 12 public void setLength( double len ) 13 { 14 length = len; 15 } 16 public double getLength() 17 { 18 return length; 19 } 20 21 static void Main(string[] args) 22 { 23 Line line = new Line(); 24 // 設(shè)置線條長(zhǎng)度 25 line.setLength(6.0); 26 Console.WriteLine("線條的長(zhǎng)度: {0}", line.getLength()); 27 Console.ReadKey(); 28 } 29 } 30 } 31 //執(zhí)行結(jié)果: 32 //對(duì)象已創(chuàng)建 33 //線條的長(zhǎng)度: 6 View Code默認(rèn)的構(gòu)造函數(shù)沒(méi)有任何參數(shù)。但是如果你需要一個(gè)帶有參數(shù)的構(gòu)造函數(shù)可以有參數(shù),這種構(gòu)造函數(shù)叫做參數(shù)化構(gòu)造函數(shù)。這種技術(shù)可以幫助你在創(chuàng)建對(duì)象的同時(shí)給對(duì)象賦初始值
代碼示例:
1 using System; 2 namespace LineApplication 3 { 4 class Line 5 { 6 private double length; // 線條的長(zhǎng)度 7 public Line(double len) // 參數(shù)化構(gòu)造函數(shù) 8 { 9 Console.WriteLine("對(duì)象已創(chuàng)建,length = {0}", len); 10 length = len; 11 } 12 13 public void setLength( double len ) 14 { 15 length = len; 16 } 17 public double getLength() 18 { 19 return length; 20 } 21 22 static void Main(string[] args) 23 { 24 Line line = new Line(10.0); 25 Console.WriteLine("線條的長(zhǎng)度: {0}", line.getLength()); 26 // 設(shè)置線條長(zhǎng)度 27 line.setLength(6.0); 28 Console.WriteLine("線條的長(zhǎng)度: {0}", line.getLength()); 29 Console.ReadKey(); 30 } 31 } 32 } 33 //執(zhí)行結(jié)果: 34 //對(duì)象已創(chuàng)建,length = 10 35 //線條的長(zhǎng)度: 10 36 //線條的長(zhǎng)度: 6 View Code(三)、析構(gòu)函數(shù)
類的?析構(gòu)函數(shù)?是類的一個(gè)特殊的成員函數(shù),當(dāng)類的對(duì)象超出范圍時(shí)執(zhí)行。
析構(gòu)函數(shù)的名稱是在類的名稱前加上一個(gè)波浪形(~)作為前綴,它不返回值,也不帶任何參數(shù)。
析構(gòu)函數(shù)用于在結(jié)束程序(比如關(guān)閉文件、釋放內(nèi)存等)之前釋放資源。析構(gòu)函數(shù)不能繼承或重載。
代碼示例:
1 using System; 2 namespace LineApplication 3 { 4 class Line 5 { 6 private double length; // 線條的長(zhǎng)度 7 public Line() // 構(gòu)造函數(shù) 8 { 9 Console.WriteLine("對(duì)象已創(chuàng)建"); 10 } 11 ~Line() //析構(gòu)函數(shù) 12 { 13 Console.WriteLine("對(duì)象已刪除"); 14 } 15 16 public void setLength( double len ) 17 { 18 length = len; 19 } 20 public double getLength() 21 { 22 return length; 23 } 24 25 static void Main(string[] args) 26 { 27 Line line = new Line(); 28 // 設(shè)置線條長(zhǎng)度 29 line.setLength(6.0); 30 Console.WriteLine("線條的長(zhǎng)度: {0}", line.getLength()); 31 } 32 } 33 } 34 //執(zhí)行結(jié)果: 35 //對(duì)象已創(chuàng)建 36 //線條的長(zhǎng)度: 6 37 //對(duì)象已刪除 View Code構(gòu)造函數(shù)在創(chuàng)建實(shí)例時(shí)調(diào)用,析構(gòu)函數(shù)在結(jié)束程序時(shí)調(diào)用。
(四)、靜態(tài)成員
我們可以使用?static?關(guān)鍵字把類成員定義為靜態(tài)的。當(dāng)我們聲明一個(gè)類成員為靜態(tài)時(shí),意味著無(wú)論有多少個(gè)類的對(duì)象被創(chuàng)建,只會(huì)有一個(gè)該靜態(tài)成員的副本。
關(guān)鍵字?static?意味著類中只有一個(gè)該成員的實(shí)例。靜態(tài)變量用于定義常量,因?yàn)樗鼈兊闹悼梢?strong>通過(guò)直接調(diào)用類而不需要?jiǎng)?chuàng)建類的實(shí)例來(lái)獲取。靜態(tài)變量可在成員函數(shù)或類的定義外部進(jìn)行初始化。你也可以在類的定義內(nèi)部初始化靜態(tài)變量。
代碼示例:
1 using System; 2 namespace StaticVarApplication 3 { 4 class StaticVar 5 { 6 public static int num; 7 public void count() 8 { 9 num++; 10 } 11 public int getNum() 12 { 13 return num; 14 } 15 } 16 class StaticTester 17 { 18 static void Main(string[] args) 19 { 20 StaticVar s1 = new StaticVar(); 21 StaticVar s2 = new StaticVar(); 22 s1.count(); 23 s1.count(); 24 s1.count(); 25 s2.count(); 26 s2.count(); 27 s2.count(); 28 Console.WriteLine("s1 的變量 num: {0}", s1.getNum()); 29 Console.WriteLine("s2 的變量 num: {0}", s2.getNum()); 30 Console.ReadKey(); 31 } 32 } 33 } 34 //執(zhí)行結(jié)果 35 //s1 的變量 num: 6 36 //s2 的變量 num: 6 View Code你也可以把一個(gè)成員函數(shù)聲明為?static。這樣的函數(shù)只能訪問(wèn)靜態(tài)變量。靜態(tài)函數(shù)在對(duì)象被創(chuàng)建之前就已經(jīng)存在。
代碼示例:
1 using System; 2 namespace StaticVarApplication 3 { 4 class StaticVar 5 { 6 public static int num; 7 public void count() 8 { 9 num++; 10 } 11 public static int getNum() 12 { 13 return num; 14 } 15 } 16 class StaticTester 17 { 18 static void Main(string[] args) 19 { 20 StaticVar s = new StaticVar(); 21 s.count(); 22 s.count(); 23 s.count(); 24 Console.WriteLine("變量 num: {0}", StaticVar.getNum()); 25 Console.ReadKey(); 26 } 27 } 28 } 29 //執(zhí)行結(jié)果: 30 //變量 num: 3 View Code將類成員函數(shù)聲明為public static無(wú)需實(shí)例化即可調(diào)用類成員函數(shù)。
反之,如果不聲明為static,即使和Main方法從屬于同一個(gè)類,也必須經(jīng)過(guò)實(shí)例化
代碼示例:
1 //示例一: 2 using System; 3 4 namespace ConsoleApp 5 { 6 class Program 7 { 8 static void Main(string[] args) 9 { 10 int num = AddClass.Add(2, 3); //編譯通過(guò) 11 Console.WriteLine(num); 12 } 13 } 14 15 class AddClass 16 { 17 public static int Add(int x,int y) 18 { 19 return x + y; 20 } 21 } 22 } 23 24 //示例二: 25 using System; 26 27 namespace ConsoleApp 28 { 29 class Program 30 { 31 static void Main(string[] args) 32 { 33 int num = Add(2, 3); //編譯錯(cuò)誤,即使改為Program.Add(2, 3);也無(wú)法通過(guò)編譯 34 Console.WriteLine(num); 35 } 36 37 public int Add(int x, int y) 38 { 39 return x + y; 40 } 41 } 42 } 43 using System; 44 45 namespace ConsoleApp 46 { 47 class Program 48 { 49 static void Main(string[] args) 50 { 51 Program self = new Program(); 52 int num = self.Add(2, 3); //編譯通過(guò) 53 Console.WriteLine(num); 54 } 55 56 public int Add(int x, int y) 57 { 58 return x + y; 59 } 60 } 61 } View Code注:
我們可以使用?static?關(guān)鍵字把類成員定義為靜態(tài)的。當(dāng)我們聲明一個(gè)類成員為靜態(tài)時(shí),意味著無(wú)論有多少個(gè)類的對(duì)象被創(chuàng)建,只會(huì)有一個(gè)該靜態(tài)成員的副本。
關(guān)鍵字?static?意味著類中只有一個(gè)該成員的實(shí)例。靜態(tài)變量用于定義常量,因?yàn)樗鼈兊闹悼梢酝ㄟ^(guò)直接調(diào)用類而不需要?jiǎng)?chuàng)建類的實(shí)例來(lái)獲取。靜態(tài)變量可在成員函數(shù)或類的定義外部進(jìn)行初始化。你也可以在類的定義內(nèi)部初始化靜態(tài)變量。
二、封裝
封裝是面向?qū)ο蟪绦蛟O(shè)計(jì)中最重要的概念之一。封裝?被定義為"把一個(gè)或多個(gè)項(xiàng)目封閉在一個(gè)物理的或者邏輯的包中"。在面向?qū)ο蟪绦蛟O(shè)計(jì)方法論中,封裝是為了防止對(duì)實(shí)現(xiàn)細(xì)節(jié)的訪問(wèn)。
抽象和封裝是面向?qū)ο蟪绦蛟O(shè)計(jì)的相關(guān)特性。抽象允許相關(guān)信息可視化,封裝則使開(kāi)發(fā)者實(shí)現(xiàn)所需級(jí)別的抽象。
C# 封裝根據(jù)具體的需要,設(shè)置使用者的訪問(wèn)權(quán)限,并通過(guò)?訪問(wèn)修飾符?來(lái)實(shí)現(xiàn)。
一個(gè)?訪問(wèn)修飾符?定義了一個(gè)類成員的范圍和可見(jiàn)性。C# 支持的訪問(wèn)修飾符如下所示:
1、public:所有對(duì)象都可以訪問(wèn);
2、private:對(duì)象本身在對(duì)象內(nèi)部可以訪問(wèn);
3、protected:只有該類對(duì)象及其子類對(duì)象可以訪問(wèn)
4、internal:同一個(gè)程序集的對(duì)象可以訪問(wèn);
5、protected internal:訪問(wèn)限于當(dāng)前程序集或派生自包含類的類型。
(一)、public
Public 訪問(wèn)修飾符允許一個(gè)類將其成員變量和成員函數(shù)暴露給其他的函數(shù)和對(duì)象。任何公有成員可以被外部的類訪問(wèn)。
代碼示例:
1 using System; 2 namespace RectangleApplication 3 { 4 class Rectangle 5 { 6 //成員變量 7 public double length; 8 public double width; 9 10 public double GetArea() 11 { 12 return length * width; 13 } 14 public void Display() 15 { 16 Console.WriteLine("長(zhǎng)度: {0}", length); 17 Console.WriteLine("寬度: {0}", width); 18 Console.WriteLine("面積: {0}", GetArea()); 19 } 20 }// Rectangle 結(jié)束 21 22 class ExecuteRectangle 23 { 24 static void Main(string[] args) 25 { 26 Rectangle r = new Rectangle(); 27 r.length = 4.5; 28 r.width = 3.5; 29 r.Display(); 30 Console.ReadLine(); 31 } 32 } 33 } 34 //執(zhí)行結(jié)果: 35 //長(zhǎng)度: 4.5 36 //寬度: 3.5 37 //面積: 15.75 View Code(二)、private
Private 訪問(wèn)修飾符允許一個(gè)類將其成員變量和成員函數(shù)對(duì)其他的函數(shù)和對(duì)象進(jìn)行隱藏。只有同一個(gè)類中的函數(shù)可以訪問(wèn)它的私有成員。即使是類的實(shí)例也不能訪問(wèn)它的私有成員。
代碼示例:
1 using System; 2 namespace RectangleApplication 3 { 4 class Rectangle 5 { 6 //成員變量 7 private double length; 8 private double width; 9 10 public void Acceptdetails() 11 { 12 Console.WriteLine("請(qǐng)輸入長(zhǎng)度:"); 13 length = Convert.ToDouble(Console.ReadLine()); 14 Console.WriteLine("請(qǐng)輸入寬度:"); 15 width = Convert.ToDouble(Console.ReadLine()); 16 } 17 public double GetArea() 18 { 19 return length * width; 20 } 21 public void Display() 22 { 23 Console.WriteLine("長(zhǎng)度: {0}", length); 24 Console.WriteLine("寬度: {0}", width); 25 Console.WriteLine("面積: {0}", GetArea()); 26 } 27 }//end class Rectangle 28 class ExecuteRectangle 29 { 30 static void Main(string[] args) 31 { 32 Rectangle r = new Rectangle(); 33 r.Acceptdetails(); 34 r.Display(); 35 Console.ReadLine(); 36 } 37 } 38 } 39 //執(zhí)行結(jié)果: 40 //請(qǐng)輸入長(zhǎng)度: 41 //4.4 42 //請(qǐng)輸入寬度: 43 //3.3 44 //長(zhǎng)度: 4.4 45 //寬度: 3.3 46 //面積: 14.52 View Code(三)、protected
Protected 訪問(wèn)修飾符允許子類訪問(wèn)它的基類的成員變量和成員函數(shù)。這樣有助于實(shí)現(xiàn)繼承。我們將在繼承的章節(jié)詳細(xì)討論這個(gè)。更詳細(xì)地討論這個(gè)。
(四)、internal
Internal 訪問(wèn)說(shuō)明符允許一個(gè)類將其成員變量和成員函數(shù)暴露給當(dāng)前程序中的其他函數(shù)和對(duì)象。換句話說(shuō),帶有 internal 訪問(wèn)修飾符的任何成員可以被定義在該成員所定義的應(yīng)用程序內(nèi)的任何類或方法訪問(wèn)。
代碼示例:
1 using System; 2 3 namespace RectangleApplication 4 { 5 class Rectangle 6 { 7 //成員變量 8 internal double length; 9 internal double width; 10 11 double GetArea() 12 { 13 return length * width; 14 } 15 public void Display() 16 { 17 Console.WriteLine("長(zhǎng)度: {0}", length); 18 Console.WriteLine("寬度: {0}", width); 19 Console.WriteLine("面積: {0}", GetArea()); 20 } 21 }//end class Rectangle 22 class ExecuteRectangle 23 { 24 static void Main(string[] args) 25 { 26 Rectangle r = new Rectangle(); 27 r.length = 4.5; 28 r.width = 3.5; 29 r.Display(); 30 Console.ReadLine(); 31 } 32 } 33 } 34 //執(zhí)行結(jié)果: 35 //長(zhǎng)度: 4.5 36 //寬度: 3.5 37 //面積: 15.75 View Code(五)、protected internal
Protected Internal 訪問(wèn)修飾符允許在本類,派生類或者包含該類的程序集中訪問(wèn)。這也被用于實(shí)現(xiàn)繼承。
注:
-
-
- ?Pubilc?:任何公有成員可以被外部的類訪問(wèn)。
- ?Private?:只有同一個(gè)類中的函數(shù)可以訪問(wèn)它的私有成員。
- ?Protected?:該類內(nèi)部和繼承類中可以訪問(wèn)。
- ?internal?: 同一個(gè)程序集的對(duì)象可以訪問(wèn)。
- ?Protected internal?:3 和 4 的并集,符合任意一條都可以訪問(wèn)。
-
1、范圍比較:private < internal/protected < protected internal < public
2、public 和 internal 修飾符的區(qū)別:
一個(gè)是國(guó)際妓女,誰(shuí)用都可以,就是 public,一個(gè)是不懂外語(yǔ)的,只能在國(guó)內(nèi)做生意,就是 internal,只能在當(dāng)前所在的工程里面引用。你建兩個(gè)工程,建立一個(gè)引用關(guān)系,被引用的里面建兩個(gè)類,就能區(qū)別了。用 VS 的話,你根本點(diǎn)不出來(lái)那個(gè)不懂外語(yǔ)的。
三、繼承
繼承是面向?qū)ο蟪绦蛟O(shè)計(jì)中最重要的概念之一。繼承允許我們根據(jù)一個(gè)類來(lái)定義另一個(gè)類,這使得創(chuàng)建和維護(hù)應(yīng)用程序變得更容易。同時(shí)也有利于重用代碼和節(jié)省開(kāi)發(fā)時(shí)間。
當(dāng)創(chuàng)建一個(gè)類時(shí),程序員不需要完全重新編寫(xiě)新的數(shù)據(jù)成員和成員函數(shù),只需要設(shè)計(jì)一個(gè)新的類,繼承了已有的類的成員即可。這個(gè)已有的類被稱為的基類,這個(gè)新的類被稱為派生類。
繼承的思想實(shí)現(xiàn)了?屬于(IS-A)?關(guān)系。例如,哺乳動(dòng)物?屬于(IS-A)?動(dòng)物,狗?屬于(IS-A)?哺乳動(dòng)物,因此狗?屬于(IS-A)?動(dòng)物。
基類與派生類:一個(gè)類可以派生自多個(gè)類或接口,這意味著它可以從多個(gè)基類或接口繼承數(shù)據(jù)和函數(shù)。 - 父類與子類。
(一)、基類的初始化
派生類繼承了基類的成員變量和成員方法。因此父類對(duì)象應(yīng)在子類對(duì)象創(chuàng)建之前被創(chuàng)建。您可以在成員初始化列表中進(jìn)行父類的初始化。
代碼示例:
1 using System; 2 namespace RectangleApplication 3 { 4 class Rectangle 5 { 6 // 成員變量 7 protected double length; 8 protected double width; 9 public Rectangle(double l, double w) 10 { 11 length = l; 12 width = w; 13 } 14 public double GetArea() 15 { 16 return length * width; 17 } 18 public void Display() 19 { 20 Console.WriteLine("長(zhǎng)度: {0}", length); 21 Console.WriteLine("寬度: {0}", width); 22 Console.WriteLine("面積: {0}", GetArea()); 23 } 24 }//end class Rectangle 25 class Tabletop : Rectangle 26 { 27 private double cost; 28 public Tabletop(double l, double w) : base(l, w) 29 { } 30 public double GetCost() 31 { 32 double cost; 33 cost = GetArea() * 70; 34 return cost; 35 } 36 public void Display() 37 { 38 base.Display(); 39 Console.WriteLine("成本: {0}", GetCost()); 40 } 41 } 42 class ExecuteRectangle 43 { 44 static void Main(string[] args) 45 { 46 Tabletop t = new Tabletop(4.5, 7.5); 47 t.Display(); 48 Console.ReadLine(); 49 } 50 } 51 } 52 //執(zhí)行結(jié)果 53 //長(zhǎng)度: 4.5 54 //寬度: 7.5 55 //面積: 33.75 56 //成本: 2362.5 View Code(二)、多重繼承
多重繼承指的是一個(gè)類別可以同時(shí)從多于一個(gè)父類繼承行為與特征的功能。與單一繼承相對(duì),單一繼承指一個(gè)類別只可以繼承自一個(gè)父類。
C# 不支持多重繼承。但是,您可以使用接口來(lái)實(shí)現(xiàn)多重繼承。
代碼示例:
1 using System; 2 namespace InheritanceApplication 3 { 4 class Shape 5 { 6 public void setWidth(int w) 7 { 8 width = w; 9 } 10 public void setHeight(int h) 11 { 12 height = h; 13 } 14 protected int width; 15 protected int height; 16 } 17 18 // 基類 PaintCost 19 public interface PaintCost 20 { 21 int getCost(int area); 22 23 } 24 // 派生類 25 class Rectangle : Shape, PaintCost 26 { 27 public int getArea() 28 { 29 return (width * height); 30 } 31 public int getCost(int area) 32 { 33 return area * 70; 34 } 35 } 36 class RectangleTester 37 { 38 static void Main(string[] args) 39 { 40 Rectangle Rect = new Rectangle(); 41 int area; 42 Rect.setWidth(5); 43 Rect.setHeight(7); 44 area = Rect.getArea(); 45 // 打印對(duì)象的面積 46 Console.WriteLine("總面積: {0}", Rect.getArea()); 47 Console.WriteLine("油漆總成本: ${0}" , Rect.getCost(area)); 48 Console.ReadKey(); 49 } 50 } 51 } 52 //執(zhí)行結(jié)果: 53 //總面積: 35 54 //油漆總成本: $2450 View Code注:
為什么一個(gè)對(duì)象可以用父類聲明,卻用子類實(shí)例化?
這個(gè)實(shí)例是子類的,但是因?yàn)槟懵暶鲿r(shí)是用父類聲明的,所以你用正常的辦法訪問(wèn)不到子類自己的成員,只能訪問(wèn)到從父類繼承來(lái)的成員。
在子類中用 override 重寫(xiě)父類中用 virtual 申明的虛方法時(shí),實(shí)例化父類調(diào)用該方法,執(zhí)行時(shí)調(diào)用的是子類中重寫(xiě)的方法;
如果子類中用 new 覆蓋父類中用 virtual 申明的虛方法時(shí),實(shí)例化父類調(diào)用該方法,執(zhí)行時(shí)調(diào)用的是父類中的虛方法;
1 /// <summary> 2 /// 父類 3 /// </summary> 4 public class ParentClass 5 { 6 public virtual void ParVirMethod() 7 { 8 Console.WriteLine("父類的方法..."); 9 } 10 } 11 12 /// <summary> 13 /// 子類1 14 /// </summary> 15 public class ChildClass1 : ParentClass 16 { 17 public override void ParVirMethod() 18 { 19 Console.WriteLine("子類1的方法..."); 20 } 21 } 22 23 /// <summary> 24 /// 子類2 25 /// </summary> 26 public class ChildClass2 : ParentClass 27 { 28 public new void ParVirMethod() 29 { 30 Console.WriteLine("子類2的方法..."); 31 } 32 33 public void Test() 34 { 35 Console.WriteLine("子類2的其他方法..."); 36 } 37 } 38 39 //執(zhí)行調(diào)用: 40 ParentClass par = new ChildClass1(); 41 par.ParVirMethod(); //結(jié)果:"子類1的方法",調(diào)用子類的方法,實(shí)現(xiàn)了多態(tài) 42 43 par = new ChildClass2(); 44 par.ParVirMethod(); //結(jié)果:"父類的方法",調(diào)用父類的方法,沒(méi)有實(shí)現(xiàn)多態(tài) View Code深究其原因,為何兩者不同,是因?yàn)樵聿煌?#xff1a;?override是重寫(xiě),即將基類的方法在派生類里直接抹去重新寫(xiě),故而調(diào)用的方法就是子類方法;而new只是將基類的方法在派生類里隱藏起來(lái),故而調(diào)用的仍舊是基類方法。
應(yīng)用舉例:
有這樣的需要,比如 People 類有一個(gè) Run 方法,Man 和 Woman 這兩個(gè)類都是繼承自 People 的類,并且都重寫(xiě)(override)了 Run 這個(gè)方法(男人女人跑起步來(lái)不一樣)。
現(xiàn)在有一群人一起跑步,有男人有女人。
我們可以把這些都裝進(jìn)一個(gè)People數(shù)組(假設(shè)為peoples)。
然后:
foreach(People p in peoples) // peoples中對(duì)象不同(即有男有女),用于實(shí)例化的子類就不同。 { p.Run(); // 故而,調(diào)用的方法也不同,實(shí)現(xiàn)了多態(tài) }由于多態(tài)性,在調(diào)用 p.Run() 的時(shí)候 p 對(duì)象本身如果是男人就會(huì)自動(dòng)調(diào)用男人的 Run 方法,是女人就會(huì)調(diào)用女人的 Run 方法。
依賴倒置原則
依賴倒置原則,DIP,Dependency Inverse Principle DIP的表述是:
1、高層模塊不應(yīng)該依賴于低層模塊, 二者都應(yīng)該依賴于抽象。
2、抽象不應(yīng)該依賴于細(xì)節(jié),細(xì)節(jié)應(yīng)該依賴于抽象。
這里說(shuō)的“依賴”是使用的意思,如果你調(diào)用了一個(gè)類的一個(gè)方法,就是依賴這個(gè)類,如果你直接調(diào)用這個(gè)類的方法,就是依賴細(xì)節(jié),細(xì)節(jié)就是具體的類,但如果你調(diào)用的是它父類或者接口的方法,就是依賴抽象, 所以 DIP 說(shuō)白了就是不要直接使用具體的子類,而是用它的父類的引用去調(diào)用子類的方法,這樣就是依賴于抽象,不依賴具體。
其實(shí)簡(jiǎn)單的說(shuō),DIP 的好處就是解除耦合,用了 DIP 之后,調(diào)用者就不知道被調(diào)用的代碼是什么,因?yàn)檎{(diào)用者拿到的是父類的引用,它不知道具體指向哪個(gè)子類的實(shí)例,更不知道要調(diào)用的方法具體是什么,所以,被調(diào)用代碼被偷偷換成另一個(gè)子類之后,調(diào)用者不需要做任何修改, 這就是解耦了。
四、多態(tài)
多態(tài)性意味著有多重形式。在面向?qū)ο缶幊谭妒街?#xff0c;多態(tài)性往往表現(xiàn)為"一個(gè)接口,多個(gè)功能"。
多態(tài)性可以是靜態(tài)的或動(dòng)態(tài)的。在靜態(tài)多態(tài)性中,函數(shù)的響應(yīng)是在編譯時(shí)發(fā)生的。在動(dòng)態(tài)多態(tài)性中,函數(shù)的響應(yīng)是在運(yùn)行時(shí)發(fā)生的。
(一)、靜態(tài)多態(tài)性
在編譯時(shí),函數(shù)和對(duì)象的連接機(jī)制被稱為早期綁定,也被稱為靜態(tài)綁定。C# 提供了兩種技術(shù)來(lái)實(shí)現(xiàn)靜態(tài)多態(tài)性。分別為:
-
-
- 函數(shù)重載
- 運(yùn)算符重載
-
運(yùn)算符重載將在下一章節(jié)討論,接下來(lái)我們將討論函數(shù)重載。
(二)、函數(shù)重載
您可以在同一個(gè)范圍內(nèi)對(duì)相同的函數(shù)名有多個(gè)定義。函數(shù)的定義必須彼此不同,可以是參數(shù)列表中的參數(shù)類型不同,也可以是參數(shù)個(gè)數(shù)不同。不能重載只有返回類型不同的函數(shù)聲明。下面的實(shí)例演示了幾個(gè)相同的函數(shù)?print(),用于打印不同的數(shù)據(jù)類型:
代碼示例:
1 using System; 2 namespace PolymorphismApplication 3 { 4 class Printdata 5 { 6 void print(int i) 7 { 8 Console.WriteLine("Printing int: {0}", i ); 9 } 10 11 void print(double f) 12 { 13 Console.WriteLine("Printing float: {0}" , f); 14 } 15 16 void print(string s) 17 { 18 Console.WriteLine("Printing string: {0}", s); 19 } 20 static void Main(string[] args) 21 { 22 Printdata p = new Printdata(); 23 // 調(diào)用 print 來(lái)打印整數(shù) 24 p.print(5); 25 // 調(diào)用 print 來(lái)打印浮點(diǎn)數(shù) 26 p.print(500.263); 27 // 調(diào)用 print 來(lái)打印字符串 28 p.print("Hello C++"); 29 Console.ReadKey(); 30 } 31 } 32 } 33 //執(zhí)行結(jié)果: 34 //Printing int: 5 35 //Printing float: 500.263 36 //Printing string: Hello C++ View Code(三)、動(dòng)態(tài)多態(tài)性
C# 允許您使用關(guān)鍵字?abstract?創(chuàng)建抽象類,用于提供接口的部分類的實(shí)現(xiàn)。當(dāng)一個(gè)派生類繼承自該抽象類時(shí),實(shí)現(xiàn)即完成。抽象類包含抽象方法,抽象方法可被派生類實(shí)現(xiàn)。派生類具有更專業(yè)的功能。
請(qǐng)注意,下面是有關(guān)抽象類的一些規(guī)則:
-
-
- 您不能創(chuàng)建一個(gè)抽象類的實(shí)例。
- 您不能在一個(gè)抽象類外部聲明一個(gè)抽象方法。
- 通過(guò)在類定義前面放置關(guān)鍵字?sealed,可以將類聲明為密封類。當(dāng)一個(gè)類被聲明為?sealed?時(shí),它不能被繼承。抽象類不能被聲明為 sealed。
-
代碼示例:
1 using System; 2 namespace PolymorphismApplication 3 { 4 abstract class Shape 5 { 6 abstract public int area(); 7 } 8 class Rectangle: Shape 9 { 10 private int length; 11 private int width; 12 public Rectangle( int a=0, int b=0) 13 { 14 length = a; 15 width = b; 16 } 17 public override int area () 18 { 19 Console.WriteLine("Rectangle 類的面積:"); 20 return (width * length); 21 } 22 } 23 24 class RectangleTester 25 { 26 static void Main(string[] args) 27 { 28 Rectangle r = new Rectangle(10, 7); 29 double a = r.area(); 30 Console.WriteLine("面積: {0}",a); 31 Console.ReadKey(); 32 } 33 } 34 } 35 //執(zhí)行結(jié)果: 36 //Rectangle 類的面積: 37 //面積: 70 View Code當(dāng)有一個(gè)定義在類中的函數(shù)需要在繼承類中實(shí)現(xiàn)時(shí),可以使用虛方法。虛方法是使用關(guān)鍵字?virtual?聲明的。虛方法可以在不同的繼承類中有不同的實(shí)現(xiàn)。對(duì)虛方法的調(diào)用是在運(yùn)行時(shí)發(fā)生的。
動(dòng)態(tài)多態(tài)性是通過(guò)?抽象類?和?虛方法?實(shí)現(xiàn)的。
代碼示例:
1 using System; 2 namespace PolymorphismApplication 3 { 4 class Shape 5 { 6 protected int width, height; 7 public Shape( int a=0, int b=0) 8 { 9 width = a; 10 height = b; 11 } 12 public virtual int area() 13 { 14 Console.WriteLine("父類的面積:"); 15 return 0; 16 } 17 } 18 class Rectangle: Shape 19 { 20 public Rectangle( int a=0, int b=0): base(a, b) 21 { 22 23 } 24 public override int area () 25 { 26 Console.WriteLine("Rectangle 類的面積:"); 27 return (width * height); 28 } 29 } 30 class Triangle: Shape 31 { 32 public Triangle(int a = 0, int b = 0): base(a, b) 33 { 34 35 } 36 public override int area() 37 { 38 Console.WriteLine("Triangle 類的面積:"); 39 return (width * height / 2); 40 } 41 } 42 class Caller 43 { 44 public void CallArea(Shape sh) 45 { 46 int a; 47 a = sh.area(); 48 Console.WriteLine("面積: {0}", a); 49 } 50 } 51 class Tester 52 { 53 54 static void Main(string[] args) 55 { 56 Caller c = new Caller(); 57 Rectangle r = new Rectangle(10, 7); 58 Triangle t = new Triangle(10, 5); 59 c.CallArea(r); 60 c.CallArea(t); 61 Console.ReadKey(); 62 } 63 } 64 } 65 //執(zhí)行結(jié)果: 66 //Rectangle 類的面積: 67 //面積:70 68 //Triangle 類的面積: 69 //面積:25 View Code注:
1、virtual和abstract都是用來(lái)修飾父類的,通過(guò)覆蓋父類的定義,讓子類重新定義。
-
-
- virtual修飾的方法必須有實(shí)現(xiàn)(哪怕是僅僅添加一對(duì)大括號(hào)),而abstract修飾的方法一定不能實(shí)現(xiàn)。
- virtual可以被子類重寫(xiě),而abstract必須被子類重寫(xiě)。
- 如果類成員被abstract修飾,則該類前必須添加abstract,因?yàn)橹挥谐橄箢惒趴梢杂谐橄蠓椒ā?/span>
- 無(wú)法創(chuàng)建abstract類的實(shí)例,只能被繼承無(wú)法實(shí)例化。
-
2、overload和override
重載(overload)是提供了一種機(jī)制, 相同函數(shù)名通過(guò)不同的返回值類型以及參數(shù)來(lái)表來(lái)區(qū)分的機(jī)制。
重寫(xiě)(override)是用于重寫(xiě)基類的虛方法,這樣在派生類中提供一個(gè)新的方法。
3、抽象方法和虛方法
-
-
- 虛方法必須有實(shí)現(xiàn)部分,抽象方法沒(méi)有提供實(shí)現(xiàn)部分,抽象方法是一種強(qiáng)制派生類覆蓋的方法,否則派生類將不能被實(shí)例化。
- ?抽象方法只能在抽象類中聲明,虛方法不是。如果類包含抽象方法,那么該類也是抽象的,也必須聲明類是抽象的。
- ?抽象方法必須在派生類中重寫(xiě),這一點(diǎn)和接口類似,虛方法不需要再派生類中重寫(xiě)。
-
簡(jiǎn)單說(shuō),抽象方法是需要子類去實(shí)現(xiàn)的。虛方法是已經(jīng)實(shí)現(xiàn)了的,可以被子類覆蓋,也可以不覆蓋,取決于需求。抽象方法和虛方法都可以供派生類重寫(xiě)。
對(duì)于面向?qū)ο蟮奶匦?#xff0c;推薦幾篇不錯(cuò)的文章:
https://www.cnblogs.com/harrogath/p/6445793.html
https://www.cnblogs.com/autumn001/p/9036148.html
?五、下期預(yù)告-敬請(qǐng)期待
->運(yùn)算符重載
->接口
->命名空間
->預(yù)處理器指令
->正則表達(dá)式
->異常處理
->文件的輸入輸出
參考文獻(xiàn):https://www.runoob.com/csharp/csharp-encapsulation.html
?根據(jù)w3school自我溫習(xí)一下c#基礎(chǔ),分享給大家。
轉(zhuǎn)載于:https://www.cnblogs.com/liu-jinxin/p/10831189.html
總結(jié)
以上是生活随笔為你收集整理的c#基础知识梳理(四)的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 关于excuteQuery与execut
- 下一篇: 年货大作《使命召唤19:现代战争2》公布