2016-09-23 12 views
0

Я написал несколько событий в FSM и обнаружил что-то, что я не могу объяснить при сопоставлении с образцом. Я думал, что следующее было полностью законным, то есть я могу отправить этого актера либо сообщение, которое является вектором [A], либо вектором [B].Как объяснить эти примеры соответствия шаблонов?

when(State) { 
    case Event(content: Vector[A], _) => { 
     println("matched A") 
     stay 
    } 
    case Event(content: Vector[B], _) => { 
    println("matched B") 
    stay 
    } 
} 

Однако если я посылаю актеру сообщение вектор [B] приводит к

java.lang.ClassCastException: B cannot be cast to A 

Так в основном он пытается соответствовать первое событие Eventhough следующий будет соответствовать.

Я попытался сделать еще более простой пример соответствия шаблону;

object Pattern extends App { 
    val n = Vector(1,2,3) 
    val s = Vector("S", "S", "S") 
    n match{ 
     case e:Vector[String] => println("matched string") 
     case v:Vector[Int] => println("matched int") 
    } 

}

Это на самом деле не является законным;

Error:(8, 12) pattern type is incompatible with expected type; 
found : Vector[String] 
required: scala.collection.immutable.Vector[Int] 
case e:Vector[String] => println("matched string") 

Однако мне разрешено запускать мой код, если я выполняю следующий приведение;

object Pattern extends App { 
    val n = Vector(1,2,3).asInstanceOf[Vector[Any]] 
    val s = Vector("S", "S", "S") 
    n match{ 
    case e:Vector[String] => println(n(0).getClass) 
    case v:Vector[Int] => println("matched int") 
    } 
} 

Вещь я нахожу странным то, что я, видимо, сказать, что любой может соответствовать строке, но печать java.lang.Integer. Поэтому я должен думать об этом, поскольку у меня есть вектор [Int], который я называю Vector [Any], поскольку Vector [Any] может быть Vector [String], он соответствует этому шаблону, и снова, поскольку он действительно является вектором [ Int] Я маскирую как Vector [Any], печать тоже прекрасна.

Может ли кто-нибудь объяснить эти наблюдения соответствия шаблону?

и как мне настроить сообщения, чтобы мое состояние могло обрабатывать оба сообщения Vector [A] и Vector [B]?

+1

Каковы '' A' и B'? Можете ли вы опубликовать [MCVE]? –

+0

A и B - классы классов. Полный и поддающийся проверке пример (в том смысле, что вы могли бы запустить его, потребовал бы гораздо больше «лишнего» кода для Akka FSM. Другой код будет работать (копировать и проезжать). – stian

+0

Вопрос не в том, что касается FSM, это о шаблоне соответствия и типах.Они могли бы изолировать проблему и легко создать воспроизводимость. –

ответ

1

Из-за стирания типа информации типа jvm во время выполнения теряется этот тип соответствия шаблонов (соответствие шаблонов с более высокими типами) не поддерживается напрямую.

Вот способы, чтобы обойти эту проблему

Вместо этого я рекомендую вам обернуть вектор в другой контейнер.

sealed trait Vectors 

case class VectorString(vs: Vector[String]) extends Vectors 

case class VectorInt(vi: Vector[Int]) extends Vectors 

def doStuff(v: Vectors) = v match { 
case VectorString(vs) => //be sure that vs is Vector[String] 
case VectorInt(vi) => 
} 

Пути спичечных картины родовых типов в Scala

Использование TypeTag

import scala.reflect.runtime.universe._ 

def handle[A: TypeTag](a: A): Unit = 
    typeOf[A] match { 
    case t if t =:= typeOf[List[String]] => 
     // list is a string list 
     val r = a.asInstanceOf[List[String]].map(_.length).sum 
     println("strings: " + r) 

    case t if t =:= typeOf[List[Int]] => 
     // list is an int list 
     val r = a.asInstanceOf[List[Int]].sum 
     println("ints: " + r) 

    case _ => // ignore rest 
    } 

val ints: List[Int] = Nil 

handle(List("hello", "world")) // output: "strings: 10" 
handle(List(1, 2, 3))   // output: "ints: 6" 
handle(ints)     // output: "ints: 0" it works! 
+0

спасибо паму. Сейчас я посмотрю. – stian