下面重點說明物件導向的三個特徵.繼承,封裝和多態.
C#是一種現代的物件導向的語言.
繼承(inheritance):繼承是一個物件導向的詞語.說明,一個類(衍生類別)能分享,其它類(基類)的特徵和行為.派
生類和基類是"is a"的關係.
base classes(基類):通常基類可以自己執行個體化,或被繼承.衍生類別繼承基類中的成員,被標記為protected或更大
的許可權.文法: class (derive class name):(base class name)
例子:
//基類
public class Contact
{
//預設私人的欄位
string name;
string email;
string address;
//建構函式
public Contact()
{
// statements ...
}
//屬性
public string Name
{
get
{
return name;
}
set
{
name = value;
}
}
public string Email
{
get
{
return email;
}
set
{
email = value;
}
}
public string Address
{
get
{
return address;
}
set
{
address = value;
}
}
}
//衍生類別
public class Customer : Contact
{
//自己的私人欄位
string gender;
decimal income;
public Customer()
{
// statements ...
}
}
在上面的例子中,Customer 是
Contact的子類,不但,繼承了父類的成員,name,email,address;還有自己的成員,gender,income.
abstract classes(抽象類別):抽象類別是一種特殊的基類.除過普通的類成員,它們還有抽象的類成員.抽象類別成員,
是不能被執行個體化的方法和屬性.所有直接從抽象類別派生的類,必須實現抽象的方法和屬性.抽象類別不能被執行個體化.
例子:
//抽象類別
abstract public class Contact
{
protected string name;
public Contact()
{
// statements...
}
//抽象方法
public abstract void generateReport();
//抽象屬性
abstract public string Name
{
get;
set;
}}
public class Customer : Contact
{
string gender;
decimal income;
int numberOfVisits;
public Customer()
{
// statements
}
public override void generateReport()
{
// unique report
}
public override string Name
{
get
{
numberOfVisits++;
return name;
}
set
{
name = value;
numberOfVisits = 0;
}
}
}
public class SiteOwner : Contact
{
int siteHits;
string mySite;
public SiteOwner()
{
// statements...
}
public override void generateReport()
{
// unique report
}
public override string Name
{
get
{
siteHits++;
return name;
}
set
{
name = value;
siteHits = 0;
}
}
}
上面的例子,定義了三個類.一個抽象類別,兩個衍生類別.實現了父類的方法和屬性."override"修飾符,實現了抽象
類的方法.
Calling Base Class Members(調用基類成員)
衍生類別能調用基類成員,如果,成員的修飾符是"protected"或更大許可權.在適當的上下文條件下,好像調用自己的
成員一樣.
例子:
abstract public class Contact
{
private string address;
private string city;
private string state;
private string zip;
public string FullAddress()
{
string fullAddress =
address + ''\n'' +
city + '','' + state + '' '' + zip;
return fullAddress;
}
}
public class Customer : Contact
{
public string GenerateReport()
{
string fullAddress = FullAddress();
// do some other stuff...
return fullAddress;
}
}
上面的例子中,衍生類別調用基類的方法:FullAddress();
基類的建構函式,可以被衍生類別調用,用base().
例子:
abstract public class Contact
{
private string address;
public Contact(string address)
{
this.address = address;
}
}
public class Customer : Contact
{
public Customer(string address) : base(address)
{
}
}
例子中,衍生類別沒有address成員,可以調用基類的建構函式.
Hiding Base Class Members(隱藏基類成員)
衍生類別可以和基類有同樣名字的成員.這時,就會隱藏基類的成員.
例子:
abstract public class Contact
{
private string address;
private string city;
private string state;
private string zip;
public string FullAddress()
{
string fullAddress =
address + ''\n'' +
city + '','' + state + '' '' + zip;
return fullAddress;
}
}
public class SiteOwner : Contact
{
public string FullAddress()
{
string fullAddress;
// create an address...
return fullAddress;
}
}
在例子中,衍生類別和基類有同樣的成員,FullAddress(),當調用時,基類的方法會被隱藏.
儘管基類的成員被隱藏,仍然可以訪問基類的成員,通過,base關鍵字,調用基類的引用.
例子:
abstract public class Contact
{
private string address;
private string city;
private string state;
private string zip;
public string FullAddress()
{
string fullAddress =
address + ''\n'' +
city + '','' + state + '' '' + zip;
return fullAddress;
}
}
public class SiteOwner : Contact
{
public string FullAddress()
{
string fullAddress = base.FullAddress();
// do some other stuff...
return fullAddress;
}
}
在例子中,衍生類別調用基類的成員,用base引用.
visioning(版本)
例子:
using System;
public class WebSite
{
public string SiteName;
public string URL;
public string Description;
public WebSite()
{
}
public WebSite( string strSiteName, string strURL, string strDescription )
{
SiteName = strSiteName;
URL = strURL;
Description = strDescription;
}
public override string ToString()
{
return SiteName + ", " +
URL + ", " +
Description;
}
}
public class Contact
{
public string address;
public string city;
public string state;
public string zip;
public string FullAddress()
{
string fullAddress =
address + ''\n'' +
city + '','' + state + '' '' + zip;
return fullAddress;
}
}
public class SiteOwner : Contact
{
int siteHits;
string name;
WebSite mySite;
public SiteOwner()
{
mySite = new WebSite();
siteHits = 0;
}
public SiteOwner(string aName, WebSite aSite)
{
mySite = new WebSite(aSite.SiteName,
aSite.URL,
aSite.Description);
Name = aName;
}
new public string FullAddress()
{
string fullAddress = mySite.ToString();
return fullAddress;
}
public string Name
{
get
{
siteHits++;
return name;
}
set
{
name = value;
siteHits = 0;
}
}
}
public class Test
{
public static void Main()
{
WebSite mySite = new WebSite("Le Financier",
"http://www.LeFinancier.com",
"Fancy Financial Site");
SiteOwner anOwner = new SiteOwner("John Doe", mySite);
string address;
anOwner.address = "123 Lane Lane";
anOwner.city = "Some Town";
anOwner.state = "HI";
anOwner.zip = "45678";
address = anOwner.FullAddress(); // Different Results
Console.WriteLine("Address: \n{0}\n", address);
}
}
例子中,衍生類別用new修飾符,說明,和基類有同樣名字的成員.
sealed classed(密封類)
密封類是不能被繼承的類.為了避免從一個類中繼承,就要產生密封類.
例子:
//密封類
public sealed class CustomerStats
{
string gender;
decimal income;
int numberOfVisits;
public CustomerStats()
{
}
}
public class CustomerInfo : CustomerStats // error
{
}
public class Customer
{
CustomerStats myStats; // okay
}
例子中,密封類不能被繼承.
封裝(Encapsulation):封裝是一個物件導向的概念,對外部世界,隱藏類的內部.
封裝優點:
1.好的封裝能減少耦合.
2.類的內部的實現可以自由改變.
3.一個類有更清楚的介面.
Data Hiding(資料隱藏):封裝的一個最有用的形式是資料隱藏.一個類的資料表現一個對象的狀態.
修飾符支援封裝:
Private:只有類本身能存取.
Protected:類和衍生類別可以存取.
Internal:只有同一個項目中的類可以存取.
Protected Internal:是Protected和Internal的結合.
Public:完全存取.
other Encapsulating Strategy:(其他封裝策略)屬性和索引器的目的是封裝一個類的細節和給類的使用者提供一個公用的介面.
封裝和繼承的關係:
封裝的意思是包容(彙總),類與類之間的關係是"has a".一個類裡面有另一個類.
繼承,類與類之間的關係是"is a".
多態(Polymorphism):就是怎樣重載一個虛擬類.多態是物件導向的重要概念.
Implementing Polymorphism(實現多態):
例子:
using System;
public class WebSite
{
public string SiteName;
public string URL;
public string Description;
public WebSite()
{
}
public WebSite( string strSiteName, string strURL, string strDescription )
{
SiteName = strSiteName;
URL = strURL;
Description = strDescription;
}
public override string ToString()
{
return SiteName + ", " +
URL + ", " +
Description;
}
}
abstract public class Contact
{
public virtual string UpdateNotify()
{
return "Web Site Change Notification";
}
}
public class Customer : Contact
{
public new string UpdateNotify()
{
return @"
This is to let you know your
favorite site, Financial Times,
has been updated with new links";
}
}
public class SiteOwner : Contact
{
WebSite mySite;
public SiteOwner(string aName, WebSite aSite)
{
mySite = new WebSite(aSite.SiteName,
aSite.URL,
aSite.Description);
}
public new string UpdateNotify()
{
return @"
This is to let you know your site, " + "\n" +
mySite.SiteName + @", has been added as
a link to Financial Times.";
}
}
public class Test
{
public static void Main()
{
WebSite leFin = new WebSite("Le Financier",
"http://www.LeFinancier.com",
"Fancy Financial Site");
Contact[] Contacts = new Contact[2];
Contacts[0] = new SiteOwner("Pierre Doe", leFin);
Contacts[1] = new Customer();
foreach (Contact poc in Contacts)
{
if (poc is SiteOwner)
{
Console.WriteLine("Message: {0}\n",
((SiteOwner)poc).UpdateNotify());
}
else
{
Console.WriteLine("Message: {0}\n",
((Customer)poc).UpdateNotify());
}
}
}
}
在例子中,Contact類有個虛擬方法,有兩個衍生類別分別實現.使用了"new"關鍵字.
可以有更有效和優雅的方法,實現它,就是多態.
例子:
using System;
abstract public class Contact
{
public virtual string UpdateNotify()
{
return "Web Site Change Notification";
}
}
public class Customer : Contact
{
public override string UpdateNotify()
{
return @"
This is to let you know your
favorite site, Financial Times,
has been updated with new links";
}
}
public class SiteOwner : Contact
{
string siteName;
public SiteOwner(string sName)
{
siteName = sName;
}
public override string UpdateNotify()
{
return @"
This is to let you know your site, " + "\n" +
siteName + @", has been added as
a link to Financial Times.";
}
}
public class Test
{
public static void Main()
{
Contact[] Contacts = new Contact[2];
Contacts[0] = new SiteOwner("Le Financier");
Contacts[1] = new Customer();
foreach (Contact poc in Contacts)
{
Console.WriteLine("Message: {0}\n",
poc.UpdateNotify());
}
}
}
例子中,衍生類別用"override"實現了多態.
虛擬方法是允許多態工作的基類的方法.用"override"修飾符說明,能被衍生類別重載.虛擬方法和抽象方法的不同
時,虛擬方法有實現,抽象方法沒有.抽象方法,隱式說明是虛擬,必須被重載;虛擬方法不必被重載.
多態,必須是虛擬方法,而且,方法的簽名必須一致,包括方法名稱,參數,和參數類型.
例子:
abstract public class Contact
{
public virtual string UpdateNotify()
{
return "Web Site Change Notification";
}
}
public class Customer : Contact
{
public override string SendMail() {}// error
public override string UpdateNotify(int number) {}// error
}
例子中,SendMail不是虛擬方法,故錯誤;UpdateNotify,帶有不同的參數,故也錯誤.
new 和 override 修飾符,都可以實現新的方法.但,new 實現的是衍生類別新的方法.
例子:
using System;
abstract public class Contact
{
public virtual string UpdateNotify()
{
return "Web Site Change Notification";
}
}
public class Customer : Contact
{
public new string UpdateNotify()
{
return @"
This is to let you know your
favorite site, Financial Times,
has been updated with new links";
}
}
public class SiteOwner : Contact
{
string siteName;
public SiteOwner(string sName)
{
siteName = sName;
}
public override string UpdateNotify()
{
return @"
This is to let you know your site, " + "\n" +
siteName + @", has been added as
a link to Financial Times.";
}
}
public class Test
{
public static void Main()
{
Contact[] Contacts = new Contact[2];
Contacts[0] = new SiteOwner("Le Financier");
Contacts[1] = new Customer();
foreach (Contact poc in Contacts)
{
Console.WriteLine("Message: {0}\n",
poc.UpdateNotify());
}
}
}
結果是:
Message:
This is to let you know your site,
Le Financier, has been added as
a link to Financial Times.
Message: Web Site Change Notification
例子中,Customer 用"new"實現新的方法,但是,在運行是不是多態.仍然調用基類的方法.
Most-Derived Implementations(多重派生實現)
Polymorphic Properties(多態的屬性):C#允許,屬性的多態實現.
例子:
using System;
public class SiteStats
{
public int numberOfVisits = 0;
}
abstract public class Contact
{
protected string name;
public virtual string Name
{
get
{
return name;
}
set
{
name = value;
}
}
}
public class Customer : Contact
{
SiteStats myStats = new SiteStats();
public override string Name
{
get
{
myStats.numberOfVisits++;
Console.WriteLine("Number of visits: {0}",
myStats.numberOfVisits);
return name;
}
set
{
base.Name = value;
myStats.numberOfVisits = 0;
Console.WriteLine("Name: {0}", Name);
}
}
}
public class Test
{
public static void Main()
{
Contact myContact = new Customer();
myContact.Name = "George";
}
}
例子中,抽象類別,有屬性Name,衍生類別重載實現了屬性.
Polymorphic Indexers(多態的索引器):索引器的多態.
例子:
using System;
using System.Collections;
public class SiteList
{
protected SortedList sites;
public SiteList()
{
sites = new SortedList();
}
public int NextIndex
{
get {
return sites.Count;
}
}
public virtual string this[int index]
{
get
{
return (string) sites.GetByIndex(index);
}
set
{
sites[index] = value;
}
}
}
public class FinancialSiteList : SiteList
{
public override string this[int index]
{
get
{
Console.WriteLine("FinancialSiteList Indexer Get");
if (index > sites.Count)
return (string)null;
return base[index];
}
set
{
Console.WriteLine("FinancialSiteList Indexer Set");
base[index] = value;
}
}
}
class SiteManager
{
SiteList sites = new SiteList();
public static void Main()
{
SiteManager mgr = new SiteManager();
mgr.sites = new FinancialSiteList();
mgr.sites[mgr.sites.NextIndex] = "Great Site!";
Console.WriteLine("Site: {0}",
mgr.sites[0].ToString());
}
}
例子中,基類的索引器是"virtual",衍生類別重載了索引器.