【问题标题】:Checking derived class arguments in Scala在 Scala 中检查派生类参数
【发布时间】:2015-11-02 11:18:18
【问题描述】:

假设以下一对类:

class A(arg:String)

class B(argList:Vector[String]) extends A(argList.first)

我希望能够在为基类构造函数提供第一个元素之前检查 argList 是否为空。不幸的是,将该检查放在B 的默认构造函数中(例如通过require,如here 所示)为时已晚,因为需要首先调用基类的构造函数。

这可能是一个更一般的 OOP 问题,但解决方案可能是 Scala 特定的。

【问题讨论】:

  • 在 java 中,在调用超级构造函数之前在构造函数中执行任何操作都会导致编译时错误。换句话说,超级构造函数 必须 是子构造函数中的第一条语句(如果省略,它会被隐式调用)。我认为 Scala 中没有解决方法。这是 Java 设计决定。

标签: scala inheritance constructor


【解决方案1】:

如果argList 为空,您希望通过什么?在任何情况下,您都可以使用以下内容:

class B(argList:Vector[String]) extends A(argList.headOption.getOrElse("your default string here")

【讨论】:

  • 这个和@Shadowlands 的解决方案的本质是headOption 方法,我不知道。谢谢两位的意见。出于平局的原因,我会接受这一点。
【解决方案2】:

解决此问题的一种方法是通过伴随对象。您可以将B 的构造函数标记为私有,以确保没有人可以绕过检查,然后将合适的apply 方法添加到预检查输入值的伴随对象:

class A(arg:String)

class B private(argList:Vector[String]) extends A(argList.head)

object B {
  def apply(argList:Vector[String]): B = argList.headOption.map(_ => new B(argList)).getOrElse(throw new RuntimeException("Oops"))
}

用法示例:

scala> B(Vector("foo", "bar"))
res2: B = B@328e9109

scala> B(Vector())
java.lang.RuntimeException: Oops
    at B$$anonfun$apply$2.apply(<console>:24)
    ...

请注意,为简单起见,我只是在处理不良数据时抛出异常,但可能会尝试其他方式来处理这种情况(@Zoltan 回答的默认值就是这样一种方式)。

【讨论】:

    【解决方案3】:

    这就是为什么在大多数地方构造函数被工厂对象所取代。在 Scala 中,将伴随对象用作工厂是惯用的。

    class A(arg: String)
    
    abstract class B(arg: String) extends A(arg) {
      def argList: IndexedSeq[String]
    }
    
    object B {
      case object Empty extends B("") {
        def argList = IndexedSeq.empty
      }
      case class NonEmpty private[B](argList: Vector[String]) extends B(argList.head)
    
      def apply(argList: Vector[String]) =
        if (argList.isEmpty) Empty else NonEmpty(argList)
    
      def unapplySeq(b:B): Option[IndexedSeq[String]] = b match {
        case Empty ⇒ Some(IndexedSeq.empty)
        case NonEmpty(args) ⇒ Some(args)
      }
    }
    

    你可以验证一下

    B(Vector()) == B.Empty
    
    B(Vector("x", "y")).isInstanceOf[B.NonEmpty]
    

    【讨论】:

      猜你喜欢
      • 2014-09-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-07-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多