Scala类构造器中如何复用其他参数为另一个参数赋值?
Scala案例类构造器参数复用解决方案
在Scala中,案例类构造器里无法直接用前面的参数作为后续参数的默认值(比如case class Foo(bar: Int, buzz: Int = bar)编译失败),以下是几种可行的实现方式:
1. 扩展伴生对象的apply方法
案例类会自动生成伴生对象和全参的apply方法,我们可以在伴生对象中新增一个单参数的apply方法,直接复用参数值:
case class Foo(bar: Int, buzz: Int) object Foo { // 新增单参数apply,将bar同时传给buzz def apply(bar: Int): Foo = Foo(bar, bar) } // 使用示例 Foo(42) // 得到 Foo(42, 42) Foo(10, 20) // 保留原全参调用逻辑,得到 Foo(10, 20)
2. 用默认标记值结合类内处理
如果希望保留构造器的默认值语法,可以用一个特殊标记值(或Option类型)作为默认值,在类初始化时替换为目标参数:
方法2.1:使用特殊数值标记(注意避免业务值冲突)
case class Foo(bar: Int, buzz: Int = Int.MinValue) { // 初始化时替换默认标记值为bar val finalBuzz = if (buzz == Int.MinValue) bar else buzz } // 使用示例 Foo(42).finalBuzz // 输出 42 Foo(42, 50).finalBuzz // 输出 50
方法2.2:使用Option类型更安全
case class Foo(bar: Int, buzz: Option[Int] = None) { val finalBuzz = buzz.getOrElse(bar) } // 使用示例 Foo(42).finalBuzz // 输出 42 Foo(42, Some(50)).finalBuzz // 输出 50
如果不想对外暴露Option参数,可以结合私有构造器和伴生对象封装:
case class Foo private (bar: Int, private val _buzz: Option[Int]) { val buzz = _buzz.getOrElse(bar) } object Foo { def apply(bar: Int): Foo = Foo(bar, None) def apply(bar: Int, buzz: Int): Foo = Foo(bar, Some(buzz)) } // 使用示例 Foo(42).buzz // 输出 42 Foo(42, 50).buzz // 输出 50
3. 辅助构造器方式(不推荐,案例类优先用伴生对象apply)
虽然案例类支持辅助构造器,但使用起来不如伴生对象的apply方法直观:
case class Foo(bar: Int, buzz: Int) { def this(bar: Int) = this(bar, bar) } // 使用示例 new Foo(42) // 得到 Foo(42, 42),注意必须加new Foo(10, 20) // 原全参调用不受影响
内容的提问来源于stack exchange,提问作者Windymelt
相关产品推荐
相关产品推荐

