2012-04-03 61 views
0

Im在加載Scala中的構造函數時遇到問題。每次我試圖傳遞一個值的過載CTOR我得到的錯誤在Scala中重載CTOR的問題

Example: 
    var client : Client = Client(*variable type List[String]()*); 

Unspecified value parameter clientList.  

我的目標是有使用2種不同的數據類型創建的對象。一個是NodeSeq和另一個列表。從來沒有。我是否正確加載CTOR或者是否有更高效的方法來實現我的目標?

package api 
import xml._ 

case class Client(clientNode: NodeSeq, clientList: List[String]) { 

    def this(clientNode: NodeSeq) = this(clientNode, null) 
    def this(clientList: List[String]) = this(null, clientList) 

    var firstName: String 
    var lastName: String 
    var phone: String 
    var street: String 
    var city: String 
    var state: String 
    var zip: String 
    var products = List[String]() 
    var serviceOrders = List[String]() 

    if (clientList == null) { 
    firstName = (clientNode \\ "firstname").text 
    lastName = (clientNode \\ "lastname").text 
    phone = (clientNode \\ "phone").text 
    street = (clientNode \\ "street").text 
    city = (clientNode \\ "city").text 
    state = (clientNode \\ "state").text 
    zip = (clientNode \\ "zip").text 

    (clientNode \\ "products").foreach(i => products = i.text :: products) 

    (clientNode \\ "serviceOrders").foreach(i => serviceOrders = i.text :: serviceOrders) 

    } else { 
    firstName = clientList(0) 
    lastName = clientList(1) 
    phone = clientList(2) 
    street = clientList(3) 
    city = clientList(4) 
    state = clientList(5) 
    zip = clientList(6) 
    } 

    override def toString(): String = { 
    return "Name : " + firstName + " " + lastName + 
     "\nAddress : " + 
     "\n\t" + street + 
     "\n\t" + city + ", " + state + " " + zip 
    } 

} 
+4

不要在Scala代碼中使用null。它只存在於與Java的互操作性。改用'Option'。 (對不起,每次我看到有人在使用'null'時都必須這樣說...)。 – Jesper 2012-04-03 19:59:00

回答

5

您沒有發佈工作代碼;你不能有未定義的變量。

無論如何,問題是即使你已經覆蓋了構造函數,你也可以用而不是覆蓋隨播對象中的構建器。收藏此,它一定會給你想要的方式:

object Client { 
    def apply(clientNode: NodeSeq) = new Client(clientNode) 
    def apply(clientList: List[String]) = new Client(clientList) 
} 

(如果你使用的REPL,所以你添加到默認的同伴對象,而不是一定要使用:paste與案件類一起進入這個替換它)。

但是更深層的問題是,這不是你應該解決問題的方式。你應該定義一個包含數據的特點,你想:

trait ClientData { 
    def firstName: String 
    def lastName: String 
    /* ... */ 
} 

,並繼承它兩次,一次爲每個方法來分析它:

class ClientFromList(cl: List[String]) extends ClientData { 
    val firstName = cl.head 
    . . . 
} 

,或者你可以打開NodeSeq到一個列表和在那裏解析它,或者其他各種各樣的東西。這樣你可以避免暴露一堆可能不會被改變的變量。

+0

由於Scala是C#,所以Kerr對Skeet來說是如此。不知道一個人可以多申請,總是這種語言的新東西;-) – virtualeyes 2012-04-03 22:07:44

+0

@virtualeyes - 我認爲這個榮譽實際上屬於Danial C. Sobral。 – 2012-04-04 00:25:19

+0

當然,但他一直在S.O.比自己長一年;-)顯然這裏有一些斯卡拉「搖滾明星」在這裏張貼,丹尼爾肯定是其中之一; Skeet的參考資料不僅僅是知識,而且是回答質量的問題,學生在那裏學習,「現在我明白了!」 @Oxbow湖也很好。無論如何,S.O.本身就是網絡上最好的教學資源;雖然我畢業了,但我還在上學;-) – virtualeyes 2012-04-04 08:00:36

0

輔助構造函數適用於簡單的單行程,不適用於這種情況。更地道的方式將是一個同伴對象來定義工廠方法:

case class Client(firstName: String, 
        lastName: String, 
        products: List[String] = Nil) 

object Client { 

    import scala.xml.NodeSeq 

    def fromList(list: List[String]): Option[Client] = 
    list match { 
     case List(firstName, lastName) => 
     Some(Client(firstName, lastName)) 
     case _ => None 
    } 

    def fromXml(nodeSeq: NodeSeq): Option[Client] = { 
    def option(label: String) = 
     (nodeSeq \\ label).headOption.map(_.text) 
    def listOption(label: String) = 
     (nodeSeq \\ label).headOption.map { 
     _.map(_.text).toList 
     } 
    for { 
     firstName <- option("firstname") 
     lastName <- option("lastname") 
     products <- listOption("products") 
    } yield Client(firstName, lastName, products) 
    } 
} 

我也參加了,通過消除可變性改進代碼,使之更加普遍安全運行的自由。