2017-02-06 9 views
0

Я совершенно новый для Scala и получил несколько нерешенных проблем со следующим кодом:Scala - не тот случай, класс и не имеет метод .unapply

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 не случай класса, а также не иметь/член Исключить unapplySeq

Ошибка: не найдено: значение Сумма

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

+1

Возможный дубликат выражения [map expression in case в scala pattern matching] (http://stackoverflow.com/questions/27051030/map-expression-in-case-clause-in-scala-pattern-matching) –

+0

@ TzachZohar нет, это не связано с этим вопросом. Здесь проблема OP не ограничивается шаблоном. OP здесь не понимает 'object',' class' и 'case class'. –

ответ

1

В Scala case class похожи на class с дополнительными плюс + некоторые другие свойства.

Для нормального класса,

class A(i: Int, s: String) 

Вы не можете создать его экземпляр, как это,

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

Вы должны будете использовать new для создания нового экземпляра.

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

Теперь давайте говорить, что мы имеем case class,

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

Мы можем создать новый экземпляр B, как это,

val b = B(5, "five") 

Причина это работает с case class, потому что case class имеют автоматически создаваемые объекты-компаньоны с ними, которые предоставляют несколько утилит, включая метод и unapply.

Таким образом, это использование val b = B(5, "five") на самом деле val b = B.apply(5, "five"). И здесь B - это не class B, а компаньон object B, который фактически продиктован apply.

Аналогичным образом сопоставление шаблонов Scala использует методы unapply (unapplySeq для моделей SeqLike), предоставляемые сопутствующим объектом. И, следовательно, обычные экземпляры class не работают с совпадением шаблонов.

Допустим, вы хотели определить class, а не case class по какой-то определенной причине, но все же хотите использовать их с сопоставлением с образцом и т. Д., Вы можете предоставить свой сопутствующий объект с помощью необходимых методов самостоятельно.

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") 
} 

Кроме того, как вы новичок в обучении Scala вы должны прочитать http://danielwestheide.com/scala/neophytes.html, который, вероятно, лучший ресурс для любого новичка Scala.