2013-06-01 80 views
2

編輯:我重寫了我的問題以闡明幷包含我想實現的目標。Scala設計幫助,抽象類或特徵上的模式匹配

我正在構建一個系統,我使用Akka發送消息。我正在使用一些小型服務來建立它。我有一個共享的核心庫,我的所有消息都駐留在案例類中。這些形成我與我的服務之間的合同。

我想做什麼就能做的是下面的,但我在抽象類信息的模式匹配出現編譯錯誤:

case class Source(serviceId: String, time: String) 
case class Credentials(tenantId:String, userId: String) 
sealed abstract class Message(credentials:Credentials, sources: Vector[Source]) 
trait FormEvent 
trait MailEvent 

case class FetchQuestion(questionId: String, credentials:Credentials, sources: Vector[Source]) extends Message(credentials, sources) with FormEvent 
case class MailQuestion(questionId: String, credentials: Credentials, sources: Vector[Sources]) extends Message(credentials, sources) with MailEvent 

def route(msg:Message, tenantId: String, sources: Vector[Source]) = msg match { 
    case fe:FormEvent => s"form message for $tenantId with sources $sources." 
    case me:MailEvent => s"mail message for $tenantId with sources $sources." 
} 

// Emulated Akka Receive, compilation error when matching. 
def receive(a: Any) = a match { 
    case [email protected](credentials, srs) => route(msg.copy(sources = (srs :+ Source("routing", "justnow"))), credentials.tenantId, srs) 
} 

所以模式匹配的合同似乎是緊密結合的情況下類,我需要採取哪些步驟來創建一個行爲類似於案例類的超類?


下面是與提取器相同的例子。

case class Source(serviceId: String, time: String) 
case class Credentials(tenantId:String, userId: String) 
case class Trail(credentials: Credentials, sources: Vector[Source]) 
trait Message { 
    def trail: Trail 
} 

object Message { 
    def unapply(msg: Message) = Option(msg.trail) 
} 

trait FormEvent 
trait MailEvent 

case class FetchQuestion(questionId: String, trail:Trail) extends Message with FormEvent 
case class MailQuestion(questionId: String, trail:Trail) extends Message with MailEvent 

def route(msg:Message, tenantId: String, newSources: Vector[Source]) = msg match { 
    case fe:FormEvent => s"form message $msg for $tenantId with sources $newSources." 
    case me:MailEvent => s"mail message $msg for $tenantId with sources $newSources." 
} 

// Emulated Akka Receive, compilation error when matching. 
def receive(a: Any) = a match { 
    case [email protected](Trail(Credentials(tenantId, _), srs)) => route(msg, tenantId, (srs :+ Source("routing", "justnow"))) 
} 

val fq = FetchQuestion("question1", Trail(Credentials("tenant", "user"), Vector(Source("service1", "before")))) 

receive(fq) 
+0

好像我正在尋找提取器。這裏是一個教程:http://danielwestheide.com/blog/2012/11/21/the-neophytes-guide-to-scala-part-1-extractors.html – Magnus

回答

0

您要找的是extractors (unapply, unapplySeq)

但是我不推薦簡化你的設計。你的多層次的繼承方式太混亂了,我沒有看到任何真正的需要。


擺脫抽象類至少讓你的繼承模式一致。但是,您的設計仍然存在問題,而且這是您過早優化的問題。

在一個正確的方法中,首先你必須發現自己在這些特定情況下的模式匹配太多,只有這樣你才能找到解決方案,而不是相反。不要試圖解決你還沒有面對的問題,並專注於你的實際問題。在大多數情況下,你會發現沒有真正需要這些優化,或者到那時你的應用程序會發生很大的變化,整個優化問題將變得過時。所以開始簡單,只有在必須時纔會變得更加複雜。

+0

不確定你的意思是具體多層次的繼承?你是指使用多個特質?我修改後的抽取器例子只使用特質,抽象類不是我自己選擇的。我有這些特性來確保我的應用程序的不同部分可以處理一般情況,而不是在模式匹配時處理任何地方最具體的情況。 – Magnus

+0

@Magnus查看我的回答更新 –

+1

我的第一篇文章(縮短了可讀性)實際上表明,我認爲解決方案變得太抽象類或具有泛型特徵的複雜。所以是的,你有一點。但這些並不是過早的優化。我將服務分成不同的JVM上的小應用程序:我需要一個統一的方式來處理交叉切割問題,並通過簡單的路由來糾正服務,例如FormEvent,MailEvent等特性,而不是在多個級別上匹配20-30種消息類型。 – Magnus