1. 程式人生 > >C#之淺析面向物件程式設計思想(一)

C#之淺析面向物件程式設計思想(一)

   縱觀MicroSoft公司的幾種主流語言,C是面向過程,VB既有面向過程也有面向物件的特性,而C#則是純粹的面向物件的程式語言。在UML的學習過程中,畫類圖、物件圖的時候面向物件的思想就已經用到了具體的學習中,而C#的學習過程中我們接著深入來學習這種思想,只不過這次是把OOP的思想用到了實際的程式碼程式設計之中。

   我們知道面向物件的四個基本原則:抽象、封裝、模組化、層次性;面向物件思想的程式設計特性:繼承性、封裝性、多型性。通過楚老師的視訊,對面向物件的四個基本原則和程式設計特性都有了新的認識,這篇部落格就先對其中的部分特性進行分析。

一、靜態變數與非靜態變數

   在上一篇部落格中,對C#基礎的分析是以“資料”引出來的,資料中變數在程式設計中佔有一席之地,那我們就從靜態變數和非靜態變數兩個角度對它進行分析。

using system;
using  system.Collections.Generic; 
using   System.text
namespace  ConsoleApplication1
{
     class  TestStatic
     {
           public static void main()
          {
                int k=AccessTest.x;    //此處直接使用,如果不是靜態變數則寫成 AccessTest myOk = newAccessTest();
                Console.WriteLine(k);
                AccessTest myOk=new AccessTest();
                Cosole.WriteLine(myOK.y);  //通過例項化才能訪問y
          }
     }
     public class AccessTest
     {
         public static int x=12;
         public int y=12;
      }
}

   由例子可知,在AccessTest類中定義了兩個變數x和y,其中x為靜態static,y為非靜態,在TestStatic類的Main函式如果要分別對AccessTest類中的x和y進行訪問,則對於x可以直接使用,而對於y需要首先例項化AccessTest類,然後再由該例項去呼叫其中的y。也就是說靜態變數中的成員可以通過類名直接進行訪問,而例項成員(非靜態變數)必須通過建立物件的引用來訪問(此處區別物件和物件引用,物件引用是一個地址而不是一個值)。我想如果x和y都定義成了非靜態變數的話,那樣程式碼量會大增的。

   通過學習,對static變數有了自己的認識,但是理解的程度僅限於此,至於在程式碼中何處該用靜態變數,還有待於在以後的學習中去探索。

二、方法

  所謂的方法,就是物件的行為,在之前學習VB的時候物件有屬性、事件和方法,而在真正面向物件的語言中沒有事件的概念,或者說事件就是屬於方法中的。

  方法的句法如下:

  [訪問修飾符] 返回值型別  <方法名> ([引數列表])//不需要返回值時用void

   {

    //方法主體

   }

   正如上面介紹的靜態變數和非靜態變數那樣,呼叫靜態的方法同樣無需進行例項化,而非靜態的方法需要進行類的例項化之後進行呼叫該方法。

   方法可以被重複呼叫即“方法過載”在C#中是一個非常重要的定義,視訊中老師將其分為“具有不同數量引數的方法過載”和“對不同資料執行相似功能的方法過載”,如下:

Using System;
Namespace chognzai
 {
   Class Class1
   {
      Public int a,b;
      Public double x,y;
      Public int fun(int a,int b)  //方法名稱相同,引數不同
      {
         Return a+b;
      }
      Public double fun(double x,double y) //方法名稱相同,引數不同
      {
         Return a+b;
      }
      Static void Main(string[] args)
      {
         Class1 sd=new Class1();
         Sd.a=156;
         Sd.b=32;
         Sd.x=23.56;
         Sd.y=56.49;
         Console.WriteLine(“{0}+{1}={2}”,sd.a,sd.b,sd.fun(sd.a,sd.b));
         Console.writeLine(“{0}+{1}={2}”,sd.x,sd.y,sd.fun(sd.x,sd.y));
         Console.ReadLine();
      }
   }
 }

    該例子中成員函式fun()被過載,屬於“對不同資料執行相似功能的方法過載”,再次驗證了方法是可以多次使用的這個觀點。

三、屬性引發的封裝性的體現

  先看個小例子,這是在視訊中非常經典的那個交電話費的例子。

namespace Customer
{
     public enum TypeofCall  
     {
         callToMobile,CallTOLandLine
      }
     class Program
      {
          static void Main(string[] args)
           {
              Customer tom=new Customer();
              tom.CustomerName="楚廣明";  //設定屬性的值
              tom.RecordCall(TypeofCall.callToMobile,20);
              tom.RecordCall(TypeofCall.callToLandline,40);
              Console.WriteLine("{0}有{1}電話費要交",tom.CustomerName,tom.customerBalance)  //讀取屬性的值
           }
      }
         public class Customer
        {
          private string name;
          private decimal balance;
          public string CustomerName  //*****屬性****//
         {
                 get( return name;)
                 set (  name=value;)
           }
           public decimal CustomerBalance //****屬性***//
            {
                get ( return balance;)   //只能讀取餘額,而不能修改
            }  
            public void RecordPayment(decimal amountpaid) //***方法*** //
            {
                balance-=amountpaid;
            }
            public void RecordCall(TypeofCall callType,uint nMinute) //***方法*** //
             {
                  swistch(callType)
                   {
                       case TypeofCall.CallToLandline:
                             balance+=(0.02M*nMinutes); 
                              break;
                        case TypeofCall.callToMobile:
                              balance+=(0.3M*nMinutes);
                          default:
                                break;
                    }
             }
          }
}

    例子有點長,其中僅僅對屬性進行分析,就像:

           public string CustomerName  //*****屬性****//

           {

                get( return name;)

                set (  name=value;)

           }

          public decimal CustomerBalance //****屬性***//

            {

               get ( return balance;)   //只能讀取餘額,而不能修改

           } 

   這兩個屬性是這個例子中的Customer類例項化後tom物件的兩個屬性,很明顯屬性區別於方法就像當初學習VB一樣,一個說明的是屬性,另一個說的是動作。從這個例子中還能體現出面向物件封裝性的思想,就像CustomerBalance屬性那樣,僅僅為讀取屬性,而沒有設定屬性的程式碼,這樣我們在主程式中就不能去修改,從而保護了隱私。也就是說通過屬性,將類的成員變數隔離,通過賦值、取值實現間隱藏封裝的功能,這也可以看做是一種許可權的限制。

    通過這個小例子,OOP的封裝性也就是通過其他間接的手段去操作類的成員變數,不要讓別人知道你的成員變數中包含著什麼,當然這裡所謂的間接手段可以是上面所提到的屬性,也可以是方法,前提是該方法的訪問修飾符是public,通過該方法呼叫相同類中訪問修飾符為private的成員變數或者成員方法,從而實現封裝,在C#視訊中有個“訪問密碼的最短長度(private)”的例子就是通過這個方法實現的。

總結:

    在C#中面向物件的思想嗎,目前僅僅是瞭解,需要急切去做的就是到《設計模式》的時候多去敲例子,多去回顧現在學的這些東西,帶著問題去學新知識,從而實現“溫故而知新”的效果。

    在接下來的面向物件總結中將對“繼承、多型”做淺析,期待。