Scala - не случайный класс и не имеет метода.unapply

Я новичок в Scala и получил несколько нерешенных проблем со следующим кодом:

   object exprs{
      println("Welcome to the Scala worksheet")

      def show(e: Expr): String = e match {
        case Number(x) => x.toString
        case Sum(l, r) => show(l) + " + " + show(r)
      }

      show(Sum(Number(1), Number(44)))
    }

    trait Expr {
      def isNumber: Boolean
      def isSum: Boolean
      def numValue: Int
      def leftOp: Expr
      def rightOp: Expr
      def eval: Int = this match {
        case Number(n) => n
        case Sum(e1, e2) => e1.eval + e2.eval
      }
    }

    class Number(n: Int) extends Expr {
      override def isNumber: Boolean = true

      override def isSum: Boolean = false

      override def numValue: Int = n

      override def leftOp: Expr = throw new Error("Number.leftOp")

      override def rightOp: Expr = throw new Error("Number.rightOp")
    }

    class Sum(e1: Expr, e2: Expr) extends Expr {
      override def isNumber: Boolean = false

      override def isSum: Boolean = true

      override def numValue: Int = e1.eval + e2.eval

      override def leftOp: Expr = e1

      override def rightOp: Expr = e2
    }

Я получаю следующие ошибки:

Ошибка: объект Number не является классом case и не имеет члена unapply/unapplySeq

Ошибка: не найдено: значение Sum

Как их решить? заранее спасибо

1 ответ

Решение

В Скала case class похожи class with extra goodies + some other properties.

For a normal class,

class A(i: Int, s: String)

You can not create its instance like this,

val a = A(5, "five")   // this will not work

Вам придется использовать new to create new instance.

val a = new A(5, "five")

Now lets say we have case class,

case class B(i: Int, s: String)

We can create a new instance of B like this,

val b = B(5, "five")

Причина, по которой это работает case class это потому что case class have an auto-created companion objects with them, which provides several utilities including an apply а также unapply метод.

So, this usage val b = B(5, "five") на самом деле val b = B.apply(5, "five"), И здесь B это не class B but the companion object B which is actually provieds apply метод.

Similarly Scala pattern matching uses the unapply (unapplySeq for SeqLike patterns) methods provided by companion object. And hence normal class instances do not work with pattern matching.

Lets say you wanted to defined a class и не case class for some specific reason but still want to use them with pattern-matching etc, you can provide its companion object with the required methods by yourselves.

class C(i: Int, s: String) {
}

object C {

  def apply(i: Int, s: String) = new C(i, s)

  def unapply(c: C) = Some((c.i, c.s))

}

// now you can use any of the following to create instances,

val c1 = new C(5, "five")

val c2 = C.apply(5, "five")

val c3 = C(5, "five")

// you can also use pattern matching,

c1 match {
  case C(i, s) => println(s"C with i = $i and s = $s")
}

c2 match {
  case C(i, s) => println(s"C with i = $i and s = $s")
} 

Also, as you are new to learning Scala you should read http://danielwestheide.com/scala/neophytes.html which is probably the best resource for any Scala beginner.

Другие вопросы по тегам