有一个案例类如下:
case class User(
id: Long,
name: String,
email: String)
我想使用Scala宏生成如下函数:
def makeUser(
id: Long = 1L,
name: String = "some name",
email: String = "some email"): User = {
User(
id = id,
name = name,
email = email)
}
它很冗长,Scala宏可以解决这种冗长问题(我希望如此)。我不太关心默认值;它们可以是随机值。
我想知道是否有人可以给我一个代码示例。谢谢。
编辑:我想澄清更多关于我想要的内容。该函数仅用于单元测试,因此我希望避免使用默认值乱丢我的case类。 (感谢@Tyler指出它。)
Edit2:另外,我想了解更多有关Scala的宏的信息。因此,如果有一个实现这一目标的宏观例子,对我来说这将是一个很好的教训。
答案 0 :(得分:3)
您不需要宏,只需将新功能添加到您的伴侣对象(或制作另一个构造函数):
case class User(id: Long, name: String, email: String)
object User {
def defaultUser(): User = {
User(1L, "name", "email")
}
}
然后使用它:
val user = User.defaultUser()
编辑:
正如@jwvh指出的那样,您可以将默认参数直接放入案例类中:
case class User(id: Long = 1L, name: String = "tyler", email: String = "tyler@email.com")
val a = User()
val b = User(email = "new@email.com")
但是,正如我在评论中提到的那样,因为看起来你正在创建这个对象的虚拟实例(可能用于测试?),我更喜欢将它与我原来的答案分开。
答案 1 :(得分:1)
我会使用scalacheck-shapeless库但是因为你正在考虑练习一些代码,这里是一个使用类型类的例子,它允许你分离类定义及其默认值。
trait Default[T] {
def get: T
}
object Default {
def apply[T](implicit ev: Default[T]): Default[T] = ev
implicit val user: Default[User] = new Default[User] {
def get: User = User(1,"name","email")
}
}
object Example {
val user = Default[User]().get
}
编辑:对于评论中的问题。我不会使用以下内容,我将其简单地用于实现目的。在这一点上,我会使用scalacheck-shapeless。然而,这接近我认为是scalacheck的实现。我认为Scalacheck也会抛出一些随机性。以下有很多初始样板,但它适用于任何只包含Int和Strings的case类(尽管你可以扩展它)。
import shapeless._
trait Default[T] {
def get: T
}
object Default {
def apply[T](implicit ev: Default[T]): Default[T] = ev
private def make[T](t: T): Default[T] = new Default[T] {
def get: T = t
}
implicit val int: Default[Int] = make(1)
implicit val string: Default[String] = make("some string")
implicit hnil: Default[HNil] = make(HNil)
implicit hlist[H, T <: HList](implicit hEv: Default[H], tEv: Default[T]): Default[H :: T] = new Default[H :: T] {
def make: H :: T = hEv.get :: tEv.ger
}
implicit gen[CC, R](implicit gen: Generic.Aux[CC, R], rEv: Default[R]): Default[CC] = {
gen.from(rEv.get)
}
}
答案 2 :(得分:0)
最终,我决定使用Scala / Java反射从案例类生成测试数据。
主要优点是(1)编译速度更快(因为它不使用宏),并且(2)API比scalacheck-shapeless更好。
操作方法如下:https://give.engineering/2018/08/24/instantiate-case-class-with-arbitrary-value.html