一、類
類包括:字段(用來存儲資料)、屬性(用來保護字段,屬性的本質是兩個函數get和set)、構造函數(用來初始化對象,給對象的每一個屬性指派)、函數(描述對象的行為)、索引器(以索引的方式去通路對象)。
一個類都可以包含兩種成員:字段(Field)與方法(Method)。
字段即變量,方法即函數。
類的字段一般代表類中被處理的資料,類的方法大多代表對這些資料的處理過程或用于實作某種特定的功能,方法中的代碼往往需要通路字段儲存的資料。
聲明為public 的變量和函數可以被外界直接通路,與此對應,private 的變量與函數,則為類的私有成員,隻能由類自己使用。
二、字段(變量)
字段(Field)代表了類中的資料,在類的所有方法之外定義一個變量即定義了一個字段。在變量之前可以加上public、private 和protected 表示字段的通路權限。以下代碼展示了在類Student 中定義的兩個公有字段Age 和SN,外界可以通過類Student 建立的對象來讀取或設定這兩個字段的值。
可以在定義字段的同時給予一個初始值,如下所示:
三、方法(函數)
一個C#函數:
傳回值類型 方法名(參數清單)
{
語句1;
語句2;
//…
return 表達式;
}
例:函數需要向外界傳回一個值,由return 語句實作。
int Add(int x, int y)
{
return x + y;
}
放在一個類中的函數(通常附加一個存取權限修飾符如public 和private)稱為“方法(method)”。
如果一個函數沒有傳回值或不關心其傳回值,則将其傳回值定義為void。
void f() //不傳回任何值的函數
{
語句1;
語句2;
//…
return ; //在return後寫一個空語句
}
四、方法的定義與使用
通路一個方法的最基本方式是通過類建立的對象。
public class MathOpt
{
public int Add(int x, int y)
{
return x + y;
}
}
class Program
{
static void Main(string[] args)
{
//建立MathOpt類的對象
MathOpt obj = new MathOpt();
//通過對象調用類的方法,結果儲存在局部變量中
int result = obj.Add(100, 200);
}
}
五、方法的重載
兩個構成重載(Overload)關系的函數必須滿足以下條件:
(1)函數名相同。
(2)參數類型不同,或參數個數不同。
需要注意的是,函數傳回值類型的不同不是函數重載的判斷條件,另外,C#是區分大小寫的語言。
class MathOpt
{
//整數相加
public int Add(int x, int y)
{
return x + y;
}
//浮點數相加
public double Add(double x, double y)
{
return x + y;
}
}
重載函數的調用:
MathOpt mathobj = null; //定義MathOpt對象變量
mathobj = new MathOpt(); //建立對象
int IResult=mathobj.Add(100, 200); //調用類的整數相加方法
double FResult = mathobj.Add(5.5, 9.2); //調用類的浮點數相加方法
Console.WriteLine("100+200=" + IResult ); //輸出結果
Console.WriteLine("5.5+9.2=" + FResult ); //輸出結果
傳給方法的實參為整數時,調用參數類型為int 的Add(int,int)方法,傳給方法實參為浮點數時,将調用參數類型為double 的Add(double , double)方法。
六、類的靜态成員
如果在聲明時沒有加“static”關鍵字,則稱之為類的“執行個體方法(instancemethod)”。加了static 關鍵字的方法稱為“靜态方法(static method)”。
加了static 關鍵字的字段稱為“靜态字段(static field)”。
靜态方法在使用時不需要建立對象,而是按以下格式直接調用:
例:計算2的3次方
double ret = Math.Pow(2, 3);//,.NETFramework 将常用的數學函數放到了類Math 中
類的執行個體方法可以直接通路類的公有靜态字段,比如數學常數π 就是Math 類的公有靜态字段,可以被用來計算圓周長:
//計算圓周長
double GetPerimeterOfCircle(Double radius)
{
return 2 * Math.PI * radius;
}
區分靜态成員與執行個體成員的典型例子:
class StaticMembers
{
public static int staticVar=0; //靜态字段
public int dynamicVar=0;
public void increaseValue()
{
staticVar++;
dynamicVar++;
}
}
以下是測試代碼:
static void Main(string[] args)
{
StaticMembers obj=null;
//建立100個對象
for (int i = 0; i < 100; i++)
{
obj = new StaticMembers();
obj.increaseValue();
}
//檢視靜态字段與普通字段的值
Console.WriteLine("dynamicVar=" + obj.dynamicVar);
Console.WriteLine("staticVar=" + StaticMembers.staticVar);
//程式暫停,敲任意鍵繼續
Console.ReadKey();
}
程式的運作結果:
dynamicVar=1
staticVar=100
因為類的靜态成員擁有以下特性:
類的靜态成員是供類的所有對象所共享的。
在本節示例中建立了100 個對象,每個對象擁有1 個dyanmicVar 字段,一共有100 個dyanmicVar 字段,這些字段是獨立的,“互不幹涉内政”。而staticVar 字段僅有一個,為所
有對象所共享。是以,任何一個對象對staticVar 字段的修改,都會被其他對象所感覺。
類執行個體成員與靜态成員的通路規則:
① 位于同一類中的執行個體方法可直接互相調用。
② 類的字段(包括執行個體字段和靜态字段)可以被同一類中的所有執行個體方法直接通路。
③類中的靜态方法隻能直接通路類靜态字段。
上述規則中,需要特别注意在靜态方法中直接調用類的執行個體方法是非法的。
例如以下代碼将無法通過編譯。
class StaticMembers
{
public static int staticVar=0; //靜态字段
public static void staticFunc() //靜态方法
{
increaseValue(); //靜态方法中不能調用執行個體方法×
dynamicVar++; //靜态方法中不能通路執行個體字段×
staticVar++; //靜态方法可以通路靜态字段正确!
}
public int dynamicVar=0;
public void increaseValue()
{
staticVar++;
dynamicVar++;
}
}
那麼,如何在靜态方法中通路執行個體資料?
很簡單,可以在靜态方法中建立對象,通過對象來通路即可。将靜态方法staticFunc()修改如下即可通過編譯:
public static void staticFunc() //靜态方法
{
//在靜态方法中通過對象通路類的執行個體成員
StaticMembers obj = new StaticMembers();
obj.increaseValue(); //調用執行個體方法,OK!
obj.dynamicVar++; //通路執行個體字段,OK!
}
七、類的屬性是一種特殊的“字段”。
在設計類時使用屬性(Property)可以保證隻有合法的資料可以傳給對象。
例:
class Student
{
private String _Name="姓名預設值";//定義一個私有的_Name 字段
public String Name//定義一個Name 屬性
{
get //讀
{
return _Name;
}
set //寫,使用隐含變量value
{
if (value.Length == 0)
throw new Exception("名字不能為空");
_Name = value;
}
}
}
class Program
{
static void Main(string[] args)
{
Student stu = new Student();
Console.WriteLine("請輸入姓名");
string value = Console.ReadLine();
stu.Name = value;
Console.WriteLine(stu.Name);//或Console.WriteLine(value);
Console.ReadKey();
}
}
編寫屬性的方法如下:
(1)設計一個私有的字段用于儲存屬性的資料;
(2)設計get 讀通路器和set 寫通路器存取私有字段資料。
C#中還允許定義隻讀屬性和隻寫屬性。
八、構造函數(constructor)
當使用new 關鍵字建立一個對象時,構造函數被自動調用。在C#中,類的構造函數與類名相同,沒有傳回值。
class A
{
//類A的構造函數
public A()
{
}
}
類的構造函數在以類為模闆建立對象時被自動調用。構造函數一般用于初始化類的私有資料字段。