2011-12-09 151 views
2

那麼,我被告知必須創建一個接受貨幣和價值的貨幣類。值應該存儲爲2個整數,一個表示美元值,另一個表示美分。限制輸入到構造函數,同時保持構造函數代碼最小

* 它應該接受精確到小數點後兩位的小數值。 *

所以我想我必須限制美分值,以便它應該只接受1到2位整數。現在,我的問題是,我的導師告訴我,在構造函數中做其他事情是不好的做法。我應該如何限制輸入,然後,如果我不能比其他的構造做任何事情:

public class Money { 
    Currency currency; 
    int dollar; 
    int cents; 

    public Money(Currency currency, int dollar, int cents) { 
     super(); 
     this.currency = currency; 
     this.dollar = dollar; 
     this.cents = cents; 
    } 
    ..... other code..... 
} 

上我應該如何實現什麼指示我的任何其他的想法?爲什麼它是不好的做法,有沒有一種方法來定義約束而不會犯這種不好的做法???

+1

您不應該將美元和美分分開。只需跟蹤美分數量,然後除以100.使用'BigInteger',而不是'int'。 此外,在其他貨幣中,這些值不被稱爲美元和美分。 請參閱http://martinfowler.com/eaaDev/quantity.html –

+0

@황현정:使用32位整數(有符號或不是)代表金錢幾乎總是代碼味道。在那裏有很多錯誤的應用程序,那裏的錯誤是或多或少的「工作」,但是應該發生高通脹(它已經發生在很多國家,它可能會再次發生),所有這些應用程序會中斷。使用64位基元(有符號或無符號)或* BigInteger *。 – TacticalCoder

+0

但BigInteger消耗太多的內存,尤其是在循環和內容中使用時,正如我已閱讀Effective Java中的內容,此外,在我的導師交給我的規範中,所以我必須遵循指示或註定!哈哈..我在想的只是將美元兌換成美分和美分,而不是使用大整數。 :D –

回答

4

你在做什麼是驗證輸入到構造函數。雖然一般來說構造函數中的「其他內容」不是最優的,但是輸入驗證代碼當然是有保證的。像下面的東西是一個很好的模式 IMO:

public Money(Currency currency, int dollar, int cents) { 
    this.currency = currency; 
    this.dollar = dollar; 
    // validate that cents is 0 to 99 
    if (cents < 0 || cents > 99) { 
     throw new IllegalArgumentException("Invalid cents value: " + cents); 
    } 
    this.cents = cents; 
} 

順便說一句,有在你的構造函數的調用前面除非super()它擴展基類中沒有點。

+0

^_ ^大聲笑..謝謝你指出。 –

+0

如果教師真的不想在構造函數中有任何東西,你可以把你的驗證放在一個私有方法中,並從構造函數中拋出IllegalArgumentException。 –

+0

你可以簡單地說'0 <=美分&&美分<100',以防止負值並避免混淆分割。 –

-1

在構造函數中添加代碼是不對的,導師是正確的。 但添加方法調用,不是。

因此,您可以將操作限制在另一個方法中,並在超級後調用它。

但是,我認爲最好的實踐是在將它傳遞給構造函數之前處理輸入限制。

將輸入解析爲單獨的類或接口類後面的代碼中。 避免使用代碼操作代表模型的東西,在這種情況下,您的「錢模型」

爲什麼它是不好的實踐?

在面向對象中,您必須編寫類,以便它們不執行他們必須知道的更多操作。在這種情況下,你的班級代表着一個對象模型,即金錢。爲什麼模型本身需要解析傳遞給它的構造函數的值? 明白了嗎?最好的實踐是傳遞已經解析和限制的構造函數的值,以便該類只需要存儲這些值。

例如,假設昨天你的約束改變了,你所要做的就是改變解析部分,而不必在Money類中寫代碼。

其他例子,有人會用你的錢類,但它會有自己的約束,他所要做的就是使用他的解析類,而不是改變你的錢類 希望它有幫助。

+0

我真的不同意在課外做「輸入限制」的想法。如果班級預計美分<100,那麼它應該驗證它。否則,假設輸入正確。這似乎是魯莽的。 – Gray

+0

而且我非常想聽聽以下聲明。 「最好的做法是將構造函數的值傳遞給已經被解析和限制的類,以便類只需要存儲這些值。」如果你正在談論Web演示對象或數據庫對象,那麼也許這是事實,但它肯定不是通用的。 – Gray

+0

在我看來,這些代表一個模型的類以及實現操作的類。多數民衆贊成我如何看待整個事情,ofc模型可以實現對其內容的操作,如轉換和返回值。但是,當然,在班級以外消毒投入仍然是最好的實踐。 –

0

我認爲人們給出這個最常見的原因是構造函數應儘可能快地消除任何併發問題,並且萬無一失,因爲構造函數有點難以診斷。

在你的情況下,簡單的數字驗證就好了。

但是,正如Marcello所說,您可能會考慮編寫驗證函數並從構造函數中調用它們,以確保一致性。

-1

如果美分值大於100,我會拋出一個ExceptionInInitializerError。要麼這樣做,要麼除以100,並將商加到美元上,把餘數加到美分上。規範化和驗證你的構造函數參數並不是一個壞習慣。

+0

不,你不應該爲任何小於虛擬機錯誤的錯誤拋出錯誤,你應該拋出'IllegalArgumentException'。 –

0

首先我不認爲這是一個不好的做法,如果通過使用構造函數得到一個無效對象,則驗證並拋出一個異常。這就是說,看着你的要求,它可能是足夠的圓角美分。最後,您可以查看其他Money實現,例如this