對象的封裝與C#的類

來源:互聯網
上載者:User

《叩開C#之門》系列之三

三、對象的封裝與C#的類

物件導向思想有三個核心要素:封裝、繼承與多態。如能正確理解這三要素,那麼基本上可以算是在編程中建立了物件導向思想。在第二節中我曾介紹,在C#中,所有資料類型的執行個體都是“對象”,不過最能體現對象特質的類型,還是“類”,同時它也是C#中最重要、最頻繁使用的類型。接下來,我將通過介紹C#的類,來充分理解對象封裝的概念。

所謂“對象”,形象地說,我們可以把它理解為一塊積木。設計積木的人需要設計積木的外觀與形狀,還有內部的材質。堆積木的人對於內部的材質並不關心,他們只需要根據不同的外觀與形狀來決定堆放的位置。因此,對於開發人員而言,要設計物件導向的程式,同時會是兩個迥然不同的身份:設計者與使用者。

先談談使用者。使用者的身份,就是利用已經提供給你的所有對象,根據需求,設計出自己需要實現的程式。就如堆積木的過程。這恰恰是物件導向編程的優勢所在,那就是“對象的重用”。已經設計好的對象,可以被不同的使用者調用,這些功能既然已經實現,對於使用者而言,當然就免去了自己去設計的過程。正如堆積木那樣,既然有了現成設計好的積木,使用者所要做的工作就是把這些積木最後組合起來,堆成不同的形狀。.Net Framework所提供的類庫,就是這樣的積木。

例如我們想把一個int類型轉換成字元型,就沒有必要自己去實現這種轉換,直接調用.Net Framework提供的功能就可以了:
int i = 10;
string s = i.ToString();

再比如我們想彈出一個Windows訊息框,同樣可以直接使用.Net Framework現有的類庫:
MessageBox.Show(“Message”);

在上述的例子中,i和MessageBox都是一個對象。

再談談設計者的身份。雖然.Net Framework的類庫功能已經非常強大,但它不可能考慮到業務的方方面面,如果需要使用一個根本就不存在的對象,此時就需要自己來設計了。例書管理系統,可能就需要使用者,圖書等對象。這就需要開發人員自己來設計這些對象。

既然最能體現“對象”思想的類型是“類”,我就來介紹一下C#中的類類型。C#中類的關鍵字是class。在一個class對象中,主要分為field(欄位)、property(屬性)和method(方法),前面兩個對應的是對象的屬性,而method則對應對象的行為。一個典型的class定義如下所示:
public class User
{
 private string m_name;
 private string m_password;
 private int m_tryCounter;
 public string Name
 {
  get {return m_name;}
  set {m_name = value;}
 }
 public string Password
 { 
  get {return m_password;}
  set {m_password = value;}
 }
 public void SignIn()
 {  
  if (m_tryCounter < 3)
  {
   if (IsValid())
   {  
    m_tryCounter = 0;
    Console.WriteLine("User {0} was signed in.", m_name);
   }
   else
   {
    m_tryCounter++;
    Console.WriteLine("User {0} is invalid. Can’t Sign in.", m_name);
   }
  }
  else
  {
   Console.WriteLine("You try to sign in more than 3 times. You are be denied.");
  }
 }
 public void SignOut()
 {
  m_tryCounter = 0;
  Console.WriteLine("User {0} was signed out.", m_name);
 } 
 private bool IsValid()
 {
  if (m_name.ToUpper() == "ADMIN" && m_password == "admin")
  {
   return true;
  }
  else
  {
   return false;
  }
 }
}

字串m_name,m_password,m_tryCounter就是類User的欄位,Name,Password是類User的屬性,而SignIn、SignOut和IsValid則是類User的方法。

關於field,property和method,我會在之後的文章中介紹,這裡主要介紹的是在這個類中出現的修飾符public、private等相關的知識。

前面說到對象好比是一個積木,設計者需要定義好這個積木的外觀和形狀,也要考慮積木內部的製作,例如選用的材質,以及是空心還是實心。如果將這個積木剖開來看,實際上該對象應分為內、外兩層。由於使用者只關心外部的實現,因此設計者就需要考慮,哪些實現應暴露在外,哪些實現應隱藏於內。這就體現了對象的封裝的思想。

封裝對象,並非是將整個對象完全包裹起來,而是根據具體的需要,設定使用者訪問的許可權。在C#中,分別用修飾符public,internal,protected,private設定,分別修飾類的欄位、屬性和方法,甚至於類對象本身:
public:表明所有對象都可以訪問;
protected internal:表明同一個程式集內的對象,或者該類對象以及其子類可以訪問;
internal:表明只有同一個程式集的對象可以訪問;
protected:表明只有該類對象及其子類對象可以訪問;(關於繼承,會在以後介紹)
private:表明只有對象本身在對象內部可以訪問;

可以看出,public的開放性最大,其次是protected internal,private的開放性最小。internal和protected置中。那麼,internal和protected哪一個開放範圍更大呢?我認為,沒有完全絕對的結論。它們的範圍前者體現一個橫向的概念,後者則體現縱向的概念。如果是internal,那麼外部程式集對象自然不能訪問,但只要是居於同一個程式集中,則所有對象都可以訪問它;如果是protected,那麼即使是外部程式集對象,只要它繼承了該對象,就可以訪問,而即使是同一程式集,如果對象不是該類對象的子類,也是無法訪問的。打一個比方,在我們的傳統文化中,是非常強調“宗族”觀念的,一個宗族的族長,對於本族人而言,權力極大,甚至掌握了生殺大權。以一個州府的範圍為例,internal就好比是知府大人,只要是該州府的百姓,都屬於他的管轄範圍,而不管他是哪一個宗族。protected則好比是宗族的族長,只要是這個宗族的成員,都要服從他,哪怕該成員屬於其他州府。我以前看過《雍正王朝》,其中就有這樣一個情節,身為皇子的胤禎,竟然無法挽救自己心愛女人的命運,因為這個女人違反了她們宗族的族規,最後眼看著她被活活燒死,卻只能黯然神傷,夢裡縈迴。

以前面定義的User類而言,所有的欄位m_name,m_password,m_tryCounter都是private的,因此User類的外部調用者無法調用它們,但請注意User類內部的方法比如SignIn或者屬性Name,卻完全可以調用。同樣的,private方法IsValid,可以被SignIn方法調用,但對於外部調用者而言,則是無法調用的。而對於public屬性Name,Password,public方法SignIn和SignOut,外部的調用者是可以訪問的。在後面的演練中,我們能夠看出這之間的區別。通過這樣分層次的封裝,就可以充分保證對象的重用性和安全性。

那麼對於類類型而言,如何確定它們的存取權限呢?這要根據實際的需求來看了。假定這個User類是用於一個電子商務網站。那麼電子商務系統在設計過程中,就需要調用到User類對象。顯然,登入與退出功能是必須提供給外部使用者的,例如登入頁面就會使用到User類。而IsValid()方法用於驗證使用者的合法性,雖然也非常必要,但該功能僅僅用於登入的時候核實使用者身份,也就是說,IsValid方法只會被SignIn方法使用,但外部實用者卻並不關心,因此,設定為private就是合理的。同樣的道理,欄位m_tryCounter也是如此。但如果需求發生改變,驗證使用者的功能不僅僅是登入的時候需要使用,在添加商品到購物車,下訂單,付款的時候,都需要該功能,那麼IsValid方法,就有必要修改為public方法了。

所以,在設計程式的時候,除了要考慮識別對象,還要充分考慮該對象的封裝。類對象內的欄位、屬性和方法,包括類本身,哪些應該暴露在外,哪些應該被隱藏,都需要根據實際的需求,給與正確的設計。

演練:
(一)設計類User,並調用該類
1、開啟Visual Studio.Net,選擇“File”菜單的“new”,選擇“Project”;
2、選擇Visual C# Projects中的“Console Application”。在Location中,定位你要儲存的項目的路徑,而名字則為“SecondExample”。該名字此時既是解決方案的名字,同時也是該項目的名字。
3、用滑鼠右鍵單擊項目名,在彈出的對話方塊中,將Assembly Name命名為SecondExample,將Default Namespace命名為:BruceZhang.com. SecondExample。
4、用滑鼠右鍵單擊項目名,選擇“Add”功能表項目的“Add Class”:
 

5、在彈出的對話方塊中,將檔案的名字命名為User.cs,
 

6、點擊“Open”按鈕後,項目中就添加了一個新的檔案User.cs。開啟該檔案,將public class User中的內容,修改為前面文中定義好的User類。
7、修改原有預設的Class1.cs(如果是Visual Studio 2005,則預設為Program.cs)檔案名稱為App.cs,然後將檔案內容修改為:
 class App
 {
  /// <summary>
  /// The main entry point for the application.
  /// </summary>
  [STAThread]
  static void Main(string[] args)
  {
   User user = new User();
   
   //使用者名稱和密碼均錯誤;
   user.Name = "Bruce";
   user.Password = "test";
   for (int i=0;i<=4;i++)
   {
    user.SignIn();
   }
   user.SignOut();

   //使用者名稱正確,密碼錯誤;
   user.Name = "admin";
   user.Password = "test";
   for (int i=0;i<=4;i++)
   {
    user.SignIn();
   }
   user.SignOut();

   //使用者名稱和密碼正確;
   user.Name = "admin";
   user.Password = "admin";
   for (int i=0;i<=4;i++)
   {
    user.SignIn();
   }
   user.SignOut();

   //注意此時是無法調用這樣的欄位和方法的;
   //user.m_name;
   //user.m_password;
   //user.IsValid();

   Console.ReadLine();
  }
 }
8、運行。

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.