什么时候使用元组而不是案例类是有意义的

问题描述 投票:5回答:3

case类Person(firstName:String,lastName:String)

VS

type Person =(String,String)// firstName,lastName

案例类显然更具可读性。但是,我看到人们使用后者。什么时候使用元组代替它?

作为后续行动

有性能差异吗?在一些语言中使用Tuple2就像使用两个原语一样,而创建一个类则会产生开销。但是Scala看起来像Tuple被实现为类。如果我想要压缩两个sequances的情况怎么样,但更喜欢输出是一个案例类,因为下面提到的所有原因。

例如

`case class UserScores(userId: Long, score: Double)`
users.zip(scores).map{(id ,score) => UserScores(id,score)}

上面的示例需要对集合进行额外的迭代,以及额外的对象创建。可以使用视图代替

users.zip(scores).view.map{(id ,score) => UserScores(id,score)}.force

但我不太确定它会产生预期的效果

scala
3个回答
6
投票

当它是最合适的抽象级别时,您应该使用元组。

例如,如果你正在编写一个框架,其中一切都是完全通用的,你可以得到的最具体的东西是“函数”,“笛卡尔积”,“半群”或类似“封闭的幺半群类”,那么你可能除了使用Tuple之外别无选择。这是一个很好的例子:Semigroupal方法:

 product[A, B](fa: F[A], fb: F[B]): F[(A, B)]

这里,元组类型的使用是完全合理的,因为接口足够抽象。

另一个例子:在整个Scala collection library中,你永远不会遇到像Person(name: String, surname: String)那样具体的东西,但相反,你会看到很多方法都适用于泛型类型(A, B)的元组。

但是,如果代码中最抽象的东西是

object Fred {
  val name = "Fred"
  val age =  "Bloggs"
}

然后你突然发现你还需要另一个类似John Doe的对象,定义它会更合适

case class Person(name: String, surname: String)

然后甚至可能像这样使用它:

val j = Person(name = "John", surname = "Doe")

当然,准确建模域名具有重要价值。这两个目标 - 准确地建模具体领域与编写在尽可能多的情况下工作的通用框架 - 是互补的。

总结一下:

  • 你在编写一个足够抽象的完全通用的框架吗?使用元组。
  • 您是否尝试尽可能地模拟某些具体领域?使用适当命名的案例类。

这里:

type Person = (String, String) //firstName, lastName

看起来像域和使用的抽象之间的不匹配。您可以简单地从编译器不会阻止您意外地交换这两个组件的事实看到它。相反,如果你使用通用的AB类型在不同的抽象级别工作,如果你不小心交换(B, A)预期有(A, B),编译器会发出错误信息。


4
投票

恕我直言,作为一般规则:

  • 默认情况下,您应该更喜欢案例类:它不会花费更多,而且更清晰
  • 此外,case类提供了许多实用的功能,例如apply,unapply和copy (来自评论:元组也有那些)
  • 一般来说,应该避免长度> 3的元组

但:

  • 对于具有多个输出的方法,这些输出通常是立即拆分的。然后使用元组
  • 在几种算法中,特别是使用功能映射/ flatMap / etc ...,你有很多中间的“单行”结果,你不需要定义一个case类。
  • 最后,正如andrey-tyukin所述,如果你正在编写泛型算法,你可能更喜欢元组。但是,你可以使用无形魔法实际上做一些很好的通用案例类代码

关于类型别名的最后一条评论:当我不想创建类时,我主要使用它们来提高可读性。这种情况发生在两种情况:

  • 别名类型是一个原语,如Int或Double,用于关键代码,我想避免装箱它们(请注意,这需要尊重其他约束才有效)
  • 当单个类型有很多含义但创建案例类时会过度设计。防爆。说几个API使用param: Map[String, Double]。 Map是一个很好的类型,你不想把它包装在一个类中。然后,在你的代码中使用ApiParams可能更具可读性

1
投票

也许如果订单无关紧要。因此,与firstName / lastName示例不同,它有区别。

仍然没有可用的信息,值是什么,但在一般情况下,可能没有信息。

© www.soinside.com 2019 - 2024. All rights reserved.