關於C#面向物件三個特徵:繼承,封裝,多型的說明
封裝(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",派生類過載了索引器.