2017-02-23 86 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的结果。