1、複習
1)方法的重載
方法的重載並非一個方法,實際上方法的重載就是一些不一樣的 方法,目的是爲了方便程序員編碼,因此將功能相近的方法命名相同
根據參數,編譯器自動的去匹配方法體,而不須要程序員記住 的方法
--》如何判斷重載寫的對不對
將方法的定義拿出來,去掉修飾符,去掉方法體,去掉返回類型
程序員
int InputNum() int InputNum(int max) int InputNum(int min,int max)
-->將參數列表中的局部變量名去掉,只留參數類型
編程
int InputNum() int InputNum(int ) int InputNum(int ,int )
2、封裝
-》屬性是對字段的封裝
-》 方法是對過程的封裝
-》類是對對象的封裝(特性和功能)
-》程序集是對類庫的封裝數組
爲何使用繼承?
-》代碼的重用
-》實現多態(里氏轉換)dom
繼承中類分爲父類(基類)與子類(派生類)ide
基類函數
將具備共同特徵的這個類,單獨寫出來,稱爲父類(基類)測試
子類this
繼承父類全部的特徵,也能夠有屬於本身不一樣的特徵。編碼
父類(基類):把這個類的對象都具備的一些特徵和行爲等都封裝到這個類裏面。
而後由這個父類派生出子類(派生類),這些子類會把父類裏的特徵(屬性)行爲(方法)等繼承下來。從而實現代碼的重用
例如:
spa
class Person { string _name; int _age; char _sex; public string Name { get { return _name; } } public int Age { get { return _age; } } public char Sex { get { return _sex; } } public Person(string name,int age,char sex) { _sex = sex; _name = name; _age = age; } public void SayHello() { Console.WriteLine("你們好,我叫{0},今年{1}歲了,我是{2}生",_name ,_age ,_sex ); } } class student : Person { public student(string name,int age,char sex):base(name,age,sex) { //方法體 } public void SayHello() { Console.WriteLine("你們好,我叫{0},今年{1}歲了,我是{2}生",Name ,Age ,Sex ); } }
這裏student類是person的派生類,它繼承了person類的全部成員包括SayHello方法,這裏Student的sayhello方法把父類的sayhello方法給隱藏了
繼承的特徵
-》單根性(只能繼承一個基類)
-》傳遞性(子類能夠繼承基類的成員。字段、屬性、方法等)
-》 派生於object根類(基於C#)(爲何要有根類?仍是爲了實現多態)
注意問題
-》構造方法的問題
建立對象的時候,好像是先調用子類構造方法,而後由子類再調用父類構造方法,
再調用構造方法的時候,其實默認有一個base(),調用了父類的無參構造方法
語法:
class 基類
{
//基類成員
}
class 子類:基類
{
//子類能夠有本身的成員
//基類的成員也會被繼承下來
}
子類於父類構造方法的執行順序
Student student = new Student();
這裏New子類對象時會先走到子類的構造方法,這裏系統會默認提供一個base()無參的構造方法。若是父類中有了有參的構造方法,系統就不會再分配無參的構造方法,
此時若是子類調用父類的構造方法就會報錯,由於父類的無參構造方法已經沒有了。解決辦法由兩個
1)再手動在父類中添加一個無參的構造方法。
2)base(參數列表)傳參數上去。
public student(string name,int age,char sex):base(name,age,sex) 這裏不執行下面的大括號,而後base調用父類的構造方法,若是父類上面還有父類會依次往上調,
直到調到最上面的父類執行完最上面的父類構造方法而後再依次的往下執行回到這個子類,執行剩下的方法體
{
//方法體
}
this和base關鍵字:
this表示當前類 當前構造方法
base表示父類 父類構造方法
經典例子:
class MyClass { public MyClass():this(3) { Console.WriteLine(1); } public MyClass(int i):this(2,3) { Console.WriteLine(i); } public MyClass(int i, int j) { Console.WriteLine("{0}{1}",i,j); } } class Program { static void Main(string[] args) { MyClass myclass = new MyClass(); } }
在new對象時首先會跳到無參的構造方法,此時看到有一個this(3),不執行方法體,在本類中尋找匹配帶一個參數的構造函數,而後調用,
此時又看到一個this(2,3),又在本類中尋找匹配帶兩個參數的構造函數,最後調用帶兩個參數的構造函數,執行帶兩個參數的方法體,
完畢以後又回到帶一個參數的構造函數中執行方法體,最後再跳會無參的構造函數中執行無參的構造函數的方法體。
4、訪問修飾符
privete 只有在本類中訪問
public 任何地方均可以訪問
protected 只能在當前類和子類中訪問
internal 只容許在當前類中訪問
protectecd internal
里氏轉換
1)子類能夠直接賦值給父類(子類對象能夠直接轉換爲父類對象)隱式轉換
2)若是知足第一個條件的父類對象,能夠強制轉換爲原來的子類對象。 強制轉換
強制轉換能夠經過 is 和 as 來判斷
is:
語法 bool b=要轉換的對象 is 要轉換的類型
若是能夠轉換就會返回一個true,若是轉換不合法就會返回一個false.
IS操做符很清晰,可是操做效率不高,另種方式是AS
as:
語法 要轉換的類型 對象=要轉換的對象 as 要轉換的類型
as操做首先測試是否合法,若是合法就轉換,若是不合法就返回null,null表示空引用
5、new和override
new隱藏基類方法: 前提是子類和父類的方法名參數返回值都同樣,這時候寫new和不寫new沒上面區別。
class MyBase { public void Func() { Console.WriteLine("我是父類"); } } class MySub : MyBase { public void Func() { Console.WriteLine("我是子類"); } }
這時候子類的方法會把父類的方法隱藏掉,這時候對象是什麼類型就調用什麼類型的方法。
override重寫基類方法:子類要重寫基類的方法,父類的方法必需要有virtual 代表是虛方法,能夠被子類重寫。
一旦父類的方法被重寫,父類的方法將不復存在,調用的時候會調用重寫以後的新的方法。
class Person //基類人類
{
//如何在子類中訪問父類的字段
//分別定義三個字段 屬性
//字段的訪問修飾符設定爲 protected 這樣在子類中即可以訪問這個字段
//protected表示當前類和子類能夠訪問
protected string _name; public string Name { get { return _name; } } protected int _age; public int Age { get { return _age; } } protected char _gender; public char Gender { get { return _gender; } }
//寫一個構造方法 將字段初始化賦值
public Person(string name, int age, char gender) { this._name = name; this._age = age; this._gender = gender; }
//定義一個無參的構造方法,這樣的話子類才能調用父類的構造函數,避免子類要調用無參的構造方法時出錯。
public Person() { } }
//定義一個supperman子類 繼承自 person
class SupperMan : Person { //子類獨有字段 特徵 private string _state; public string State { get { return _state; } } public SupperMan(string name, int age, char gender, string state) //這裏不寫base()默認調用父類無參的構造方法,寫與不寫都同樣 { base._name = name; base._age = age; base._gender = gender; base._state = state; //*this 是表示這是該類中的一個字段 //*base則表示這是一個從父類中繼承過來的字段 //*在這裏 this 與base能夠不寫 是寫給程序員看的 } public void Hello() { Console.WriteLine("你們好,我叫{0},個人年齡是{1},我是{2}人,個人特徵是{3}",Name,Age,Gender,State); } } class Program { static void Main(string[] args) { SupperMan supperMan = new SupperMan("超人", 28, '男', "內褲外穿"); supperMan.Hello(); Console.ReadKey(); } }
2)構造方法
--》沒有繼承關係
-》默認構造方法(無參的構造方法)
沒有提供構造方法的時候, 系統自動的添加一個無參的構造方法
若是已經寫了構造方法,那麼系統就不會自動的添加默認的構造方法(手動添加)
-》構造方法也有重載
調用
this(當調用制定構造方法後有this的時候,會先調用this表示的重載,再調用本身的構造方法)
--》有繼承關係
-》默認調用父類的構造方法
-》使用base能夠指定調用父類構造方法
靜態構造方法
靜態構造方法從程序的開始到結束只會被調用執行一次,當new對象或者訪問這個類的字段或屬性等時就會調用執行,
多態實現的前提:
-》繼承
-》子類父類方法名必須相同
里氏轉換原則(只是實現多態的一個條件不是前提)
-》父類 父類對象=new 子類();
。。。
子類 子類對象=(子類)父類對象 必須知足上面的條件這裏才能轉換成功
隱藏基類的方式
只須要在子類的方法前寫上new關鍵字便可(不寫也能夠,系統會自動添加)
隱藏看類型
class Person { public void SayHello() { Console.WriteLine("依依呀呀"); } } class American : Person { public new void SayHello() { Console.WriteLine("Hello"); } } class Korean : Person { public new void SayHello() { Console.WriteLine("啊你喲哈撒喲"); } }
重寫基類方法
-》在父類方法前加上virtual
-》在子類方法前加上override
重寫只管新
class Person { public virtual void SayHello() { Console.WriteLine("依依呀呀"); } } class American : Person { public override void SayHello() { Console.WriteLine("Hello"); } } class Korean : Person { public override void SayHello() { Console.WriteLine("啊你喲哈撒喲"); } }
2、產生隨機數
Random:專門處理隨機數的類。(僞隨機數,其運行原理是:先獲得系統的當前時間(精確到毫秒),而後根據系統的當前時間計算出一個數(就是所謂的僞隨機數))
--》建立隨機對象
Random r=nrw Radom();
注意: 隨機數的對象不要建立在循環裏 否則會獲得一些重複同樣的數字
-->調用Next方法的獲得隨機數
-》next方法有三個重載
int res=r.netx(); 產生一個非負數的隨機數
int res=r.next(100); 產生一個0到99的隨機數,兩端能夠取到
int res=r.next(2,30);產生一個2到29的隨機數,兩端能夠取到
記錄時間的類
Stopwath:
Stopwath stop=new Stopwath();
stop.start(); 開始計算
.....
stop.Stop(); 中止計算
console.writeLine(stop.Elapsed); 獲得計算結果
多態:爲了程序的可擴展性
-》開放封閉的原則(對擴展開放,對修改封閉)
多態的使用:
將不一樣的對象都當作父類來看,屏蔽掉各個對象間的不一樣,寫出通用代碼,作出通用編程,
3、抽象類
什麼是抽象方法
有些時候父類的方法不須要實現
有些時候不知道怎麼實現
沒有方法體的方法叫作抽象方法,使用abstact修飾,
包含抽象方法的類,也必須是一個抽象類。
抽象類中能夠包含非抽象成員
抽象方法的用法和虛方法的用法徹底同樣
不一樣的是他們的定義不同,抽象類不能夠實例化
抽象類存在就是爲了被繼承的,所以不容許定義爲private.
抽象類不能實例化,比通常類多一抽象成員
抽象類與通常類有兩個最大的區別
--》不能實例化
--》 具備抽象成員 ( 凡是跟方法有關的均可以抽象)
-》方法
-》屬性
-》索引器(帶參數的屬性)
-》事件的聲明(能夠看作「屬性」,屬性石一個get set方法,事件是add remove方法)
使用抽象屬性的時候,通常是抽象類提供屬性以及可訪問性
子類提供字段與屬性的實現
public abstract string s
{
get; //這裏的屬性和自動屬性長得很像,可是要注意他們的含義不同,這裏由abstract修飾就是告訴系統,這裏是抽象方法沒有方法體,因此這裏不用寫{}
set; //抽象屬性能夠只有get或set,由於他能夠由構造方法給字段賦值,而自動屬性是後臺自動生成字段,因此自動屬性的get set要成對出現
}
4、重寫ToString方法
string[] str = { "1", "2", "3", "4" }; MyClass myClass = new MyClass(); myClass.Name1 = "我是MyClass"; myClass.Name2 = "0"; myClass.Name3 = "3"; myClass.Name4 = "4"; myClass.Name5 = "5"; MyStruct myStruct; myStruct.Name = "我是MyStruct"; Console.WriteLine(str); Console.WriteLine(myClass); Console.WriteLine(myStruct);
這裏打印數組和類系統會默認調用ToString()方法 任何類型都有一個ToString()方法,由於這個方法是object根類提供的,C#裏全部的類都繼承自object類,因此object的ToString()會被繼承下來。
Reflector能夠看到object的ToString()方法是個虛方法,若是子類沒有重寫,那麼系統都會默認調用這個方法,
能夠看到這個方法調用 this.GetType()方法 (得到當前實力的命名空間),而後返回
因此上面打印出來的是這個實例所在的命名空間名和實例名。
public virtual string ToString() { return this.GetType().ToString(); }
既然父類提供的是虛方法那子類就能夠重寫,咱們能夠經過子類重寫ToString()方法來實現咱們想要顯示的內容
class MyClass { public string name1; public override string ToString() { return name1; } } class Program { static void Main(string[] args) { MyClass myClass = new MyClass(); myClass.name1 = "張三"; Console.WriteLine(myClass);//這裏會顯示 張三 Console.ReadKey(); } }
//本系列會持續更新。晚安!