2012-06-02 35 views
1

我想檢查構造函數參數並拒絕構造拋出IllegalArgumentException(如果參數設置無效(值不符合預期約束))。同時檢查應該在修改對象時設置相同的參數集的同時工作。如何在Scala中編寫這個代碼?構造函數調用期間和創建對象後的參數驗證

scala> class Rectangle (var Length:Double, var Width:Double){ 
    | if (Length <0) 
    | throw new IllegalArgumentException("The Length must be Non-negative") 
    | if (Width <0) 
    | throw new IllegalArgumentException("The Width must be Non-negative") 
    | def setLength(l:Double) = Length = l 
    | } 
    defined class Rectangle 

    scala> var R = new Rectangle (-9, -9) 
    java.lang.IllegalArgumentException: The Length must be Non-negative 
at Rectangle.<init>(<console>:9) 

    scala> var R = new Rectangle (0, -9) 
    java.lang.IllegalArgumentException: The Width must be Non-negative 
at Rectangle.<init>(<console>:11) 



    scala> var R = new Rectangle(9, 9) 
    R: Rectangle = [email protected] 


    scala> R.Length 
    res7: Double = 9.0 

    scala> R.Width 
    res8: Double = 9.0 

    scala> R.setLength(18) 

    scala> R.Length 
    res10: Double = 18.0 

    scala> R.setLength(-9) 
    // R.setLength should not the set the Length to -9. ************************** 
    scala> R.Length 
    res12: Double = -9.0 

回答

2

它必須是可變的嗎?

case class Rectangle(length:Double, width:Double) { 
    if (length < 0) 
    throw new IllegalArgumentException("The Length must be Non-negative") 
    if (width < 0) 
    throw new IllegalArgumentException("The Width must be Non-negative") 
    def setLength(l: Double) = copy(length=l) 
} 
+0

是的。它必須是可變的。@ Debilski – Optimight

+0

從哪裏可以瞭解有關copy(length = l)函數/運算符的更多信息?任何文章/鏈接/ pdf? – Optimight

+0

@ user1417244你可以使用'scalac -Xprint:typer'。例如:'echo'case class Rectangle(length:Double,width:Double)'> test.scala && scalac -Xprint:typer test.scala'。你會得到這個:'def copy(length:Double = length,width:Double = width):Rectangle = new Rectangle(長度,寬度)' – senia

2

你需要一個屬性setter/getter方法。

class Rectangle(private var l: Int, private var w: Int) { 
    require(l > 0, "Invalid length: " + l + " <0 ") 
    require(w > 0, "Invalid width: " + w + " <0 ") 
    def length = l 
    def width = w 
    def length_=(len: Int) { require(len > 0, "Invalid length: " + len + " < 0"); l = len } 
    def width_=(wid: Int) { require(wid > 0, "Invalid width: " + wid + " < 0"); w = wid } 
    override def toString = length + ", " + width 
} 
+0

對於每個參數(即本例中的長度),我們不能只有一個驗證控制點而不是兩個控制點。 – Optimight

+0

@ user1417244:根據需要製作它。你爲什麼不採取不變的解決方案。 –

2

可變狀態是一個壞主意,但如果你需要它,不希望驗證的兩個點,你可以使用王子約翰·韋斯利的略微修改的方案:

class Rectangle(l: Int, w: Int) { 

    private[this] var _length: Int = _ 
    private[this] var _width: Int = _ 
    def length: Int = _length 
    def width: Int = _width 
    def length_=(len: Int) { require(len > 0, "Invalid length: " + len + " < 0"); _length = len } 
    def width_=(wid: Int) { require(wid > 0, "Invalid width: " + wid + " < 0"); _width = wid } 

    length = l 
    width = w 

    override def toString = length + ", " + width 
} 
+0

你的代碼工作得很好。你能指導「_length」和「length_」中'_(下劃線)'的含義嗎?從哪裏可以瞭解更多關於他們的信息? – Optimight

+0

@Optimight這是初始化爲默認值。請參閱[在stackoverflow上的這個答案](http://stackoverflow.com/a/8001132/406435)。 – senia

2

我不喜歡到目前爲止提到的答案。你的問題是參數必須有效才能創建一個對象。其他解決方案中止對象創建,但在我看來,你真正想要的不是墮胎,而是在創建對象之前進行一些檢查。爲了實現這一點,你需要的工廠:

object Rectangle { 
    def apply(length:Double, width:Double): Rectangle = { 
    require(length >= 0, "The Length must be Non-negative") 
    require(width >= 0, "The Width must be Non-negative") 
    new Rectangle(length, width) 
    } 
} 
class Rectangle private(val length:Double, val width:Double) { 
    def length_=(l: Double) = Rectangle(l, width) 
} 

這裏唯一的問題是,我們是不允許創建一個案例類的時候,我們要定義我們自己的應用,方法(有作爲類的構造相同的方法簽名) 。

+0

我在你的答案中嘗試了代碼。但它允許創建新的Rectangle(-1,-1),由於非負參數而不應該發生這種情況。請指導。 – Optimight

+0

您的觀點 - 對象創建不應中止是絕對有效的,也是最理想的。而不是新的矩形(-1,-1)... var Rect = Rectangle(-1,-1)可以根據需要正常工作。 – Optimight

+0

@優化:是的,我的錯。這不應該工作。我將ctor設置爲私人。 – sschaef

相關問題