four design examples for the add function as class or instance methods

物件導向程式設計在規劃一個運算方法時,面臨兩種選擇

  1. 運算要定義為類別方法物件方法
  2. 運算結果要定義為方法回傳值,或覆蓋原物件

這兩者選擇完全取決於設計者。底下以簡單的整數加法運算為例,說明定義為類別方法物件方法回傳結果覆蓋原物件,其製作及使用上的差別。 一般是類別設計者參考下面表格先決定運算要如何使用,再決定如何製作。


回傳結果 覆蓋原物件
類別方法 範例: sum=Integer.add(3, 5) → 回傳 8
特性: 不改變原物件,偏向函數式設計
範例: Integer.addInPlace(obj, 5) → obj 由 3 變成 8
特性: 直接修改物件,副作用明顯
物件方法 範例: sum=obj.add(5) → 回傳新物件值 8,原 obj 仍為 3
特性: 保留原物件,方便鏈式操作
範例: obj.addInPlace(5) → obj 由 3 變成 8
特性: 高效但有副作用,難以追蹤狀態
A.四種加法運算的個別設計範例如下:

(1) 類別方法回傳結果
 public class WholeNumber
 {
    public int number;

    public WholeNumber(int n)
    {
      this.number = n;
    }

    public String toString()
    {
      return String.format("%d", number);
    }

    public static WholeNumber add(WholeNumber n1, WholeNumber n2)
    {
      WholeNumber n = new WholeNumber(0);
      n.number = n1.number + n2.number;
      return n;
    }

    public static void main(String args[])
    {
      WholeNumber n1 = new WholeNumber(3);
      WholeNumber n2 = new WholeNumber(4);

      // 呼叫加法運算時,須傳入兩個運算元n1,n2,並預期=號接收新結果物件n3
      WholeNumber n3 = WholeNumber.add(n1, n2);

      // n3:7 = n1:3 + n2:4
      System.out.printf("n3:%s = n1:%s + n2:%s\n", n3, n1, n2);
    }
  } 


(2) 類別方法結果覆蓋原物件
 public class WholeNumber
 {
    public int number;

    public WholeNumber(int n)
    {
      this.number = n;
    }

    public String toString()
    {
      return String.format("%d", number);
    }

    public static void add(WholeNumber n1, WholeNumber n2)
    {
      WholeNumber n = new WholeNumber(0);
      n.number = n1.number + n2.number;
      n1.number = n.number;
    }

    public static void main(String args[])
    {
      WholeNumber n1 = new WholeNumber(3);
      WholeNumber n2 = new WholeNumber(4);
      WholeNumber n1_copy = new WholeNumber(3);

      // 呼叫加法運算時,須傳入兩個運算元n1,n2,並預期n1由結果覆蓋
      WholeNumber.add(n1, n2);<

      // n1:7 = n1:3 + n2:4
      System.out.printf("n1:%s = n1:%s + n2:%s\n", n1, n1_copy, n2);
    }
  } 


(3) 物件方法回傳結果
 public class WholeNumber
 {
    public int number;

    public WholeNumber(int n)
    {
      this.number = n;
    }

    public String toString()
    {
      return String.format("%d", number);
    }

    public WholeNumber add(WholeNumber n2)
    {
      WholeNumber n = new WholeNumber(0);
      n.number = this.number + n2.number;
      return n;
    }

    public static void main(String args[])
    {
      WholeNumber n1 = new WholeNumber(3);
      WholeNumber n2 = new WholeNumber(4);

      // 呼叫加法運算時,只額外傳入運算元n2,並預期=號接收新結果物件n3
      WholeNumber n3 = n1.add(n2);

      // n3:7 = n1:3 + n2:4
      System.out.printf("n3:%s = n1:%s + n2:%s\n", n3, n1, n2);
    }
 } 


(4) 物件方法結果覆蓋原物件
 public class WholeNumber
 {
    public int number;

    public WholeNumber(int n)
    {
      this.number = n;
    }

    public String toString()
    {
      return String.format("%d", number);
    }

    public void add(WholeNumber n2)
    {
      WholeNumber n = new WholeNumber(0);
      n.number = this.number + n2.number;
      this.number = n.number;
    }

    public static void main(String args[])
    {
      WholeNumber n1 = new WholeNumber(3);
      WholeNumber n2 = new WholeNumber(4);
      WholeNumber n1_copy = new WholeNumber(3);

      // 呼叫加法運算時,只額外傳入運算元n2,並預期n1由結果覆蓋
      n1.add(n2);

      // n1:7 = n1:3 + n2:4
      System.out.printf("n1:%s = n1:%s + n2:%s\n", n1, n1_copy, n2);
    }
 }


B.四種加法運算的整合設計範例如下,將四種寫法合併成一支類別,方便比較四種用法的不同:


 class WholeNumber
 {
    public int number;

    // 建構子
    public WholeNumber(int n)
    {
      this.number = n;
    }
    
    // 拷貝建構子
    public WholeNumber(WholeNumber n)
    {
      this.number = n.number;
    }

    // 列印方法
    public String toString()
    {
      return String.format("%d", number);
    }

    // 類別方法,結果由新物件回傳
    public static WholeNumber classAddReturn(WholeNumber n1, WholeNumber n2)
    {
      WholeNumber n = new WholeNumber(0);
      n.number = n1.number + n2.number;
      return n;
    }

    // 類別方法,結果覆蓋n1物件
    public static void classAddOverwrite(WholeNumber n1, WholeNumber n2)
    {
      WholeNumber n = new WholeNumber(0);
      n.number = n1.number + n2.number;
      n1.number = n.number;
    }

    // 物件方法,結果由新物件回傳
    public WholeNumber instanceAddReturn(WholeNumber n2)
    {
      WholeNumber n = new WholeNumber(0);
      n.number = this.number + n2.number;
      return n;
    }

    // 物件方法,結果覆蓋本物件
    public void instanceAddOverwrite(WholeNumber n2)
    {
      WholeNumber n = new WholeNumber(0);
      n.number = this.number + n2.number;
      this.number = n.number;
    }

    // 測試四種加法的主程式
    public static void main(String args[])
    {
      WholeNumber n1,n2,n3,n4,n1_copy;
      
      n1 = new WholeNumber(3);
      n2 = new WholeNumber(4);
      
      // 呼叫加法運算時,須傳入兩個運算元n1,n2,並預期=號接收新結果物件n3
      n3 = WholeNumber.classAddReturn(n1, n2);
      
      // n3:7 = n1:3 + n2:4
      System.out.printf("n3:%s = n1:%s + n2:%s\n", n3, n1, n2);


      n1_copy = new WholeNumber(n1);
      // 呼叫加法運算時,須傳入兩個運算元n1_copy,n2,並預期n1_copy由結果覆蓋
      WholeNumber.classAddOverwrite(n1_copy, n2);
      
      // n1:7 = n1:3 + n2:4
      System.out.printf("n1:%s = n1:%s + n2:%s\n", n1_copy, n1, n2);


      // 呼叫加法運算時,只額外傳入運算元n2,並預期=號接收新結果物件n4
      n4 = n1.instanceAddReturn(n2);

      // n4:7 = n1:3 + n2:4
      System.out.printf("n4:%s = n1:%s + n2:%s\n", n4, n1, n2);


      n1_copy = new WholeNumber(n1);
      // 呼叫加法運算時,只額外傳入運算元n2,並預期本物件n1_copy由結果覆蓋
      n1_copy.instanceAddOverwrite(n2);

      // n1:7 = n1:3 + n2:4
      System.out.printf("n1:%s = n1:%s + n2:%s\n", n1_copy, n1, n2);
    }
 } 

沒有留言:

When to use Java String, StringBuffer, or StringBuilder?

在 Java 開發中,處理文字字串是最常見的操作之一。然而,許多初學者仍容易混淆 String 、 StringBuffer 與 StringBuilder 的使用時機。 選擇錯誤的工具不僅會影響程式的執行效率(Performance),在多執行...

總網頁瀏覽量