2017-02-23 60 views
1

我的模型看起來是這樣的:案例類的構造函數參數給出的元組

abstract class A(id:String, val time:Int) extends Ordered[A]{ 
    override def compare(that:TrackingEvent) = this.time.compare(that.time) 
} 

case class B(id:String, override val time: Int, x:Int, y:int) extends A(id,time) { 
    //some methods 
} 
// more Case Classes who inherit from A 

我從MongoDB中得到一些數據,並將它們存儲在某些情況下,類(每類從A繼承)

我目前做的是這樣的:

val header = getHeader(doc) //doc => actual row, return: Tuple2(String,Int) 
val xy = getXYDatapoint(doc) // return: Tuple2(Int,Int) 
val b = B(header._1,header._2,xy._1,xy._2) 

每個繼承類的情況下使用相同的getHeader(DOC)函數來獲得頭。 (這就是爲什麼抽象類A有兩個參數)

我希望它看起來更好,這樣我可以殺死一些行。

喜歡的東西:

val b = B(header+xy) 

還是其他什麼東西。我可以改變整個Scala代碼,並會打開任何幫助,讓它看起來更好(我在斯卡拉是新)

我試着用無形的,但沒有奏效:

import shapeless._ 
import syntax.std.tuple._ 

val header = getHeader(doc) 
val xy = getXY(doc) 
val param = header++xy 

val b = (B.apply _).tupled(param) // didn't work because param is of type prepend.Out 
val b = (B.apply _).tupled(("a",2,3,4)) // would work 

當有人知道一些很好的提示或技巧,我很樂意聽到它。

回答

1

你真的很接近;你只需要明確地說你想要的類型是一個元組。以下是所有需要幫助的示例:

import shapeless.syntax.std.tuple._ 

case class Test(a: Int, b: Int, c: String, d: Int) 

val tuple: (Int, Int, String, Int) = (1, 2) ++ ("a", 3) 

Test.tupled(tuple) // works 

但是,如果我可以添加,您的用例可以通過一些額外的建模來簡化。那麼你根本就不需要無形。最近我看到很多人濫用案例課程。它們的目的是作爲抽象數據類型(ADT),而不是一般意義上的類。如果你的案例類需要包含一些邏輯,那麼最好把它變成一個類。

雖然您確實有案例類的用例。爲什麼不在兩個獨立的ADT中捕獲有關標題和數據點的信息?

下面是完整的代碼:

case class Header(id: String, time: Int) 
case class DataPoint(x: Int, y: Int) 

abstract class A(id: String, val time: Int) { 
    // whatever 
} 

class B(header: Header, dataPoint: DataPoint) extends A(header.id, header.time) { 
    // whatever 
} 

val dataPoint = DataPoint(1, 2) 
val header = Header("header", 42) 

val b = new B(header, dataPoint) 

當然,如果類A的參數idtime語義是那些從標題的,你甚至可以讓A舉一個參數:abstract class A(header: Header)

個人而言,我認爲這是乾淨,清晰和良好的模型。當然,你的意見可能會有所不同。:)

+0

我覺得你的第二點真的很有趣。但是當你有一個需要一個數組的類C時,需要2個字符串的類D,......你還會這樣做嗎? – Boendal

+0

它總是取決於用例。你有C,D等,每種都有不同的數據類型,但都表示標題,或者它們是來自不同的東西(不僅僅是標題)的一大堆'id'和'time's?順便說一句,讓我們不要過度延伸這裏的討論:)我們解決了主要問題(案例類<->元組)。我給了你一個有關設計的暗示,但對於它的進一步問題,我們總是可以在gitter或某個地方見面,或者你可以發佈後續問題。 – slouc

+0

如果您願意,我們可以在這裏討論:https://gitter.im/scala/scala – slouc

1

你可以定義另一個應用方法的情況下類:

case class B(id: String, override val time: Int, x: Int, y: Int) extends A(id, time) 
object B { 
    def apply(header: (String, Int), coordinates: (Int, Int)): B = 
    B(header._1, header._2, coordinates._1, coordinates._2) 
} 

現在你可以使用它作爲:

val header = getHeader(doc) 
val coords = getXY(doc) 
val b = B(header, coords) 

這是很好的,因爲你不需要調用tupled了,您只需使用新的應用方法構建您的實例,並直接傳遞getHeadergetXY的結果。