總結一下這兩天的學習筆記,正所謂溫故而知新嘛,希望能夠更好的學習後面的新知識
1、面向對象概念
面向對象三大特征:封裝、繼承、多態
2、類對象是引用傳遞
把一個對象傳遞到方法中,傳遞的也是這個對象本身的引用,修改這個對象會影響外面的對象
3、null
表示變量沒有指向任何對象
值類型(ValueType):數值類型(int、long、double等)、boolean等基本類型,枚舉、結構體的值是復制傳遞,不能為null;
String不是值類型
4、局部變量和成員變量
(1)局部變量必須初始化,成員變量聲明時已經默認初始化了(基本數值類型初始化值為0;布爾類型默認初始化值為false;string類型初始化值為null)
(2)當成員變量和局部變量(函數參數也可以看做局部變量)重名的時候,成員變量被看做局部變量,為避免混亂,訪問成員變量時加上"this.","this"表示當前對象;
5、public和private
class test { public int age;//被public修飾,這個成員變量可以被外部和這個類自己訪問 private string name;//被private修飾,這個成員變量只能被這個類內部訪問 //可以聲明一個setName方法來提供給外界 外部通過這個方法操作給內部的私有變量name賦值 public void setName(int name) { this.name=name; } }
可以把成員變量聲明為public,也可以聲明為private,成員變量聲明為private 就只能在類的內部調用private成員
public成員可以被類內部或者外界訪問,private成員只能被內部訪問,這樣可以保護不希望外界調用的內部成員,包含(字段(Field)變量、方法)不被外界訪問
字段(Field)/成員變量(Member Variable)一般聲明為private。通過get/set方法進行取值/賦值;
6、屬性
為避免外界給成員變量隨便賦值,必須把成員變量聲明為private,然後提供get/set方法,寫起來、調用起來都麻煩,C#提供屬性的一個語法
屬性的聲明
給一個私有成員變量聲明屬性給外界讀取寫入
private int age;//聲明一個私有變量,外界不能訪問 public int Age { get { return this.age;//外界通過Age的返回值拿到age變量的值, } set { //value就是外界傳入的值,屬性賦值時調用set方法把外界的值賦值給本類的私有變量age this.age=value; } }
屬性的簡化,如果是簡單的get/set邏輯,可以有更簡單的寫法:
public int Age { get; set; }
get、set可以單獨聲明為private、protected,這樣就可以設置不同的訪問級別了
如果屬性只有get或者set方法就是只讀或者只寫屬性。只讀只寫都不能簡寫。
7、構造函數入門
(1)構造函數是創建類對象,並且在創建完成前對類進行初始化的特殊函數。如果定義的類是沒有聲明構造函數,則編譯器編譯時會默認給出一個無參構造函數,如果定義了任意一個有參構造函數,則不會提供默認無參的構造函數。
(2)構造函數的格式及特點:
方法名必須和類名一致
沒有返回值類型
構造函數可以重載
下面是代碼示例:
1 class Person 2 { 3 //無參的構造方法, 4 //如果自己重新寫了一個構造函數,默認無參的構造函數會被干掉,要用的話需要自己寫一個 5 public Person()//沒有返回值,方法名和類名一致 6 { 7 } 8 9 public Person(int age)//只有一個參數的有參構造函數 10 { 11 //this.age = age; 12 Age = age; 13 } 14 15 public Person(int age, string name)//有兩個參數的構造函數 16 { 17 //this.age = age; 18 Age = age; 19 //this.name = name; 20 Name = name; 21 } 22 23 private int age; 24 25 public int Age 26 { 27 get { return age; } 28 set { age = value; } 29 } 30 private string name; 31 32 public string Name 33 { 34 get { return name; } 35 set { name = value; } 36 } 37 public void SayHello() 38 { 39 Console.WriteLine("name="+name+";age="+age); 40 } 41 } 42 43 //調用 44 static void Main(string[] args) 45 { 46 Person p1 = new Person();//new對象時調用無參構造方法 47 p1.SayHello(); 48 49 Person p2 = new Person(19);//調用只有int類型參數的構造方法 50 p2.SayHello(); 51 52 Person p3 = new Person(30, "張三");//調用有int類型參數和string類型的構造方法 53 p3.SayHello(); 54 55 Console.ReadKey(); 56 } View Code
8、static介紹
(1)一些場景下會要求一個類的多個實例共享一個成員;有時候想定義一些不和具體對象關聯、不需要new就調用的方法;
舉例:Console類的WriteLine;MessageBox的Show
(2)static方法不需要new就可以直接通過類名調用;
(3)static變量是共享的內存空間,非static變量則是對象隔離的;
(4)static方法中無法使用this關鍵字,因為static獨立於對象存在,不是任何人的唯一;
(5)static成員只能訪問static成員,不能接訪問非static成員。非static成員可以訪問static成員。
9、命名空間
可以用文件系統的文件重名和文件夾來解釋命名空間的問題
命名空間語法:namespace 命名空間名稱
當前命名空間中的類無需引用;使用using引用其它包中的類;
還可以通過“命名空間+類名”的方式使用“System.Data.SqlClient.SqlConnection” ,不用using,適用於同時使用多個重名的類,比uising時候的別名好;
10、繼承(inherit)
C#中一個類可以“繼承”自其它類,如果A繼承B,則A叫做B的子類,B叫做A的父類(基類)。子類會從父類繼承所有非private成員。子類還可以有子類;
C#中一個類只能有一個父類,如果沒有指定父類,則System.Object為父類
子類的構造方法默認都去訪問父類的無參構造方法;在子類的構造方法後都有一行默認語句base()
class Fu { public Fu() { Console.WriteLine("FU"); } } class Zi:Fu { public Zi():base()//不管是否顯式調用base(),new 子類對象時控制台都會輸出fu { Console.WriteLine("zi"); } } //new子類對象時,先去執行父類的構造函數把父類初始化完成,再去初始化子類的。 Zi z = new Zi();
可以通過 base(參數) 去訪問父類中的有參構造函數。見下面代碼:
class Fu { public Fu(int a)//父類定義了一個有參的構造函數,則沒有無參的構造函數 { Console.WriteLine("FU"+a); } } class Zi:Fu { public Zi():base(0)//如果父類沒有無參的構造函數,則需要顯示調用父類的其它的有參構造函數 { Console.WriteLine("ZI"); } public Zi(int a):base(a) { Console.WriteLine("ZI"+a); } }
定義了一個有參的構造函數,則沒有無參的構造函數,父類沒有無參的構造函數,則需要顯示調用父類的其它的有參構造函數
11、private、public和protected的區別
public成員可以被所有類訪問
private成員無法被子類和外部類訪問,子類只能通過父類的public方法“間接”訪問父類的private成員。這樣保證了父類private成員的安全性。
protected成員只能被自己以及自己的子類(直接或者間接)訪問,無法被“外姓人”訪問。
12、多態
面向對象三大特征:封裝、繼承、多態。多態是面向對象最強大的一個特征,也是最難的一個特征,設計模式等都是多態的表現
子類中定義和父類中一樣的方法就叫“重寫(override)或覆蓋”,父類中可以被override的方法要聲明為virtual。
override修飾符
class DiQiuRen { //public void SayHello() public virtual void SayHello()//父類中希望子類可以 override的方法標注virtual { Console.WriteLine("我是地球人"); } } class ZhongGuoRen : DiQiuRen { //public void SayHello() public override void SayHello()//子類中override父類中的同樣的方法必須標注override { Console.WriteLine("我是中國人"); } }
調用:
//調用 static void Main(string[] args) { ZhongGuoRen zgr1 = new ZhongGuoRen(); zgr1.SayHello();//中國人子類override父類的方法,所以調用的是ZhongGuoRen的SayHello方法 //可以用父類的變量指向子類的對象 DiQiuRen dqr1 = new ZhongGuoRen(); dqr1.SayHello();//調用的方法實現還是對象的實現,而不是變量的實現,調用的還是new出來的對象的方法 //dqr1.BaiNian();不管實際指向的是什麼類型的對象,能夠調用什麼方法取決於變量的類型 }
父類變量可以指向子類對象,內存中也還是子類對象,有且只有這一個對象 變量是什麼類型沒關系,到底執行誰的方法主要取決於內存中的對象是什麼類型的
抽象類
抽象類的抽象方法主要用來限制子類“必須實現這些抽象方法”;子類也可以不實現,那麼子類也要是抽象類,由子類的子類...去實現。試想一下:如果子類繼承了抽象類而你沒有實現抽象方法,萬一你調用了抽象方法怎麼辦?我這個抽象方法沒有具體的實現,你叫我怎麼調用?
抽象方法
抽象方法沒有方法體;一旦類中定義了抽象方法,類必須被修飾為抽象;抽象類無法實例化(new);
13、接口
語法:
public interface ISpeakable { void speak();//不提供體具體實現連{}都不用 }
(1)接口是一種用聲明"能力"的類型,不提供具體實現
(2)不提供實現方法,連{}都不能有
(3)接口無法實例化,只能被類“實現”
public class TeacherCang:ISpeakable//繼承接口 { public void speak()//實現接口的方法 { Console.WriteLine("yamadie"); } }
(4)既可以使用接口類型變量又可以使用類類型變量調用speak
(5)接口的意義是定義“做什麼”,類定義“怎麼做”
(6)接口中不能聲明變量(字段)一個沒有實現代碼的接口聲明變量沒有意義
(7)接口可以定義多個方法,也可以不定義任何方法(* 標識接口)
(8)接口是“能力”不是實現,因此也不能定義構造函數(沒這個必要)
(9)類只有一個父類,類可以實現多個接口