[C#] 跟著Ouch寫程式 – 第二課 class中的劇本 : Method

  • 6023
  • 0
  • C#
  • 2013-07-14

經過了上一課,相信大家對基本的程式邏輯都有了基本的認識,而我們在前言篇有講到,在C#中,通常一個Class裡面會有幾個固定的成員,有用來描述屬性的Property和Field,還有一個是專門處理「動作」的,也就是我們今天要講的主角「Method」(方法),但是在其他語言裡面(像是Java和ActionScript),它被叫做Function(函式),其實指的都是同一種東西。



經過了上一課,相信大家對基本的程式邏輯都有了基本的認識,而我們在前言篇有講到,在C#中,通常一個Class裡面會有幾個固定的成員,有用來描述屬性的Property和Field,還有一個是專門處理「動作」的,也就是我們今天要講的主角「Method」(方法),但是在其他語言裡面(像是Java和ActionScript),它被叫做Function(函式),其實指的都是同一種東西。

在C#的程式命名規範裡面,就很明確的定義出Property和Field必需是以「名詞」來命名,而Method必需是以「動詞」做為開頭來命名,這也直接的點出了Method的用途,通常是被用來「處理」或是「進行」某件事情的,我們也可以把它看作是在class中定義好的「劇本」,之後利用該class創建出來的實體(也就是角色)的動作,都得乖乖的按照這些定好的劇本來演。就拿我們前言中提到的範例來說,一個角色會有許多的動作,例如跳舞、攻擊、坐下,這些就會被定義成Method。

Method通常都是可以被拿來重複運用的,就像一個角色可以重複的做跳舞、坐下和攻擊這些動作一樣;除此之外,Method也會因為不同的需求,搭配不同的傳入「參數」(如果把Method看作是劇本,那參數就是道具或是其他角色了),來完成某些特定的動作。舉例來說,要跳舞,可能可以選擇不同的舞步;而要攻擊,也可能會需要傳入不同的目標,來達到攻擊不同的角色。只要Method和參數配合得當,我們就可以做到「寫一次程式,就能應付不同的情況和需求」這件事。另外,除了可以傳入參數之外,Method也可以依照不同的需求,決定有沒有回傳的值。
 

一般而言,Method的結構通常如下:

clip_image002

 

在我們要更深入了解Method之前,先跟大家再補充幾個重要的觀念:

  1. 我們在前言有講到,一個class會有它所謂的建構子,class只是一個用來包裝物件屬性和可以做的行為的「軀殼」,其實建構子也是一個Method,我們得透過使用new這個關鍵字呼叫建構子,來創建一個class的Instance(實體,可以想像成能透過呼叫建構子這個方法來替class注入靈魂)。
  2. 物件的階層觀念是透過.()這個符號來表達,而大部份的程式語言開發工具中,都有智慧提示的功能,只要在class的實體名稱後面輸入.(),工具就會自動列出該class中可供存取或是呼叫的Property或是Method以供選擇。
  3. 在同一個class內,可以透過this關鍵字或是直接以來存取class本身的Property、Field和Method(例如this.Name),也可以直接以Property、Field和Method的名稱直接存取。
  4. 在C#中,敘述式必需以;(分號)做為結尾。

相信大家看了上面的紙上談兵,應該還是霧煞煞,這邊我們就來寫些小範例,幫助大家了解Method的結構和用法吧!!

首先呢,我們一樣來實作一個Character類別,為了不要搞得太複雜,我們就只定義三個Property和兩個Method就好。

Character.cs

public class Character
{
    //建構子
    public Character()
    {
 
    }
 
    //角色名稱 Field
    private string _name;
 
    //角色名稱 Property
    public string Name
    {
        get
        {
            return _name;
        }
        set
        {
            _name = value;
        }
    }
 
    //角色等級 Field
    private int _level;
 
    //角色等級 Property
    public int Level
    {
        get
        {
            return _level;
        }
        set
        {
            _level = value;
        }
    }
 
    //角色HP Field
    private int _healthPoint;
 
    //角色HP Property
    public int HealthPoint
    {
        get
        {
            return _healthPoint;
        }
        set
        {
            _healthPoint = value;
        }
    }
 
    //攻擊Method,需要傳入一個型別為Character的參數
    public void Attack( Character character )
    {
        character.HealthPoint -= CountAttactPower();
 
        this.HealthPoint -= character.CountAttactPower();
    }
 
    //計算攻擊力Method,公式為等級x3,不需傳入參數,會將計算出來的值以整數型別回傳。
    public int CountAttactPower()
    {
        return this.Level * 3;
    }
}

 

以上面的例子來說,我們就為Character這個類別定義出了兩個公開的Method。

接下來我們來利用Character這個class來寫個小範例,讓大家更有fu一點,在範例中,我要以Character這個class來創建兩個角色的實體,並且讓兩個角色互相攻擊。


//以Character這個Class的預設建構子建立一個叫做character1的實體
Character character1 = new Character();
 
//對character1實體的三個屬性分別賦與初始值
character1.Name = "尼古拉伯爵";
character1.Level = 85;
character1.HealthPoint = 40000;
 
//以Character這個Class的預設建構子建立一個叫做character2的實體
Character character2 = new Character();
 
//對character2實體的三個屬性分別賦與初始值
character2.Name = "巫喵王";
character2.Level = 91;
character2.HealthPoint = 2000000;
 
//呼叫character1的Attack Method,並傳入character2做為參數,讓character1攻擊character2
character1.Attack( character2 );
 
//呼叫character2的Attack Method,並傳入character1做為參數,讓character2攻擊character1
character2.Attack( character1 );

 

這裡再來針對上面的程式做個簡單的說明:

前面有提到,class只是軀殼,我們必需透過呼叫它的建構子來替它注入靈魂,上面的new Character()就是在做這件事。
而Character character1 = new Character();這行的意思就是:我們宣告一個名稱為character1,型別為Character的物件,並且透過Character預設的建構子建立一個Character的實體,並把該建立出來的實體值存到character1中,因為character1是由Character這個class所創建出來的,因此它也會具有在Character這個class中所定義過的Property、Field和Method,因此我們也就可以直接存取character1裡面的Property和Method了。(請反複閱讀這一段,直到有fu為止,真的沒辦法有fu的話,麻煩請撥以下電話....啊~不是,是請和我聯絡,我再想看看有沒有更好的解釋方式)

image

再來我們要看的重點,是在我們分別呼叫了character1和character2的Attack()這個Method之後發生的事:
當我們呼叫了character1的Attack這個Method的時候,傳入了character2當作參數,因此在character1.Attack這個Method裡的運作如下圖:

image

所以當執行完character1.Attack( character2 );之後,character2的HealthPoint屬性會變成2000000 - ( 85 * 3 ) = 1999745;character1的HealthPoint屬性會變成40000 - ( 91 * 3 ) = 39727。
執行之後的character2.Attack(character1);時,character2的Attack這個Method的運作則會變成:

image

執行完character2.Attack( character1 );之後,character1的HealthPoint屬性會變成39727 - ( 91 * 3 ) = 39454;character2的HealthPoint屬性會變成1999745 - ( 85 * 3 ) = 1999490。
以上就是Method很基本的使用法。

不過!!Method還有另一種進階版的應用方式叫做Recursive(遞迴),可以藉由在Method裡面再次呼叫Method本身做到類似於迴圈的效果,來看個小範例:


public int SumNumber( int number , int sum )
{
    if( number > 0 )
    {
        sum += number--;
        return SumNumber( number , sum );
    }
 
    return sum;
}

 

如果要計算10+9+8…+1的值,就可以透過呼叫SumNumbers( 10 , 0 )來完成。
Method是學習C#中非常重要的一環,只要對C#中內建的class和它的Method夠熟的話,寫起程式來就能節省很多的時間,大家有空的話多多研究吧!!