2016-10-02 3 views
1

Если я случай класс определен нижеПонимание пробоя тематических классов

case class Calculator(brand: String, model: String) 

Как это метод компаньона исключить его объект будет выглядеть? Какие аргументы он примет?

Я не могу эмулировать это, определяя класс, а затем сам его сопутствующий объект.

class abc (age:Int, name:String) { 
} 

object abc { 
    def apply(age:Int, name:String) = new abc(age, name) 
    def unapply(obj:abc) = Some("test") 
} 

abc(1, "aaaa") 
res6: abc = [email protected] 

res6 match { 
    | case abc(1, "aaaa") => println("found") 
    | } 

error: too many patterns for object abc offering String: expected 1, found 2 
       case abc(1, "aaaa") => println("found") 
       ^
<console>:14: error: type mismatch; 
found : Int(1) 
required: String 
       case abc(1, "aaaa") => println("found") 

ответ

2

Tzach бить меня к нему ..

Ваше сообщение об ошибке кстати. из-за несоответствия между опцией, которую возвращает unapply (которая содержит одну строку), и совпадением в вашем case case (с желанием сопоставления с парой).

Вы могли бы включать в себя нулевую проверку просто чтобы убедиться (компилятор делает, для случая класса компаньона объектов):

class Abc(val age: Int, val name: String) 

object Abc { 
    def unapply(obj: Abc): Option[(Int, String)] = 
    if (obj == null) 
     None 
    else 
     Some((obj.age, obj.name)) 
} 

Shameless самореклама: Если вы заинтересованы в более подробной информации о поиске по шаблону, вы можете найти мою маленькую презентацию "Everything you always wanted to know about pattern matching" полезной.

3

Вам нужно сделать age и name членов вашего класса, чтобы они были доступны после строительства (можно сделать, делая их val с), а затем использовать их в unapply:

class abc (val age:Int, val name:String) 

object abc { 
    def apply(age:Int, name:String) = new abc(age, name) 
    def unapply(candidate: abc) = Some((candidate.age, candidate.name)) 
} 

Какой будет соответствовать правильно:

scala> new abc(2, "bbbb") match { 
|  case abc(1, "aaaa") => println("found 1") 
|  case abc(2, "bbbb") => println("found 2") 
|  case _ => println("not found") 
|  } 
found 2 
2

Если вы хотите создать пользовательский класс, который имеет unapply способа и хочет использовать Extractor Pattern с ним, the following rules should apply:

Тип возврата к unapply должен быть выбран следующим образом:

  • Если это просто тест, вернуть Boolean. Например case even()
  • Если она возвращает одно подполе значение типа T, возвращает Option[T]
  • Если вы хотите вернуть несколько подвидов стоимостей T1,...,Tn, сгруппировать их в необязательном кортеж Option[(T1,...,Tn)].

Как правило, это означает, что для вас, например, все, что должно быть сделано с помощью метода unapply является третьим вариантом, который возвращает кортеж значений. После этого, в отличие от класса case, который автоматически создает неизменяемые поля для вас, вам нужно добавить аннотацию val к вашему объявлению класса.

class abc (val age: Int, val name: String) 

И:

def unapply(obj: abc): Option[(Int, String)] = Some((obj.age, obj.name))