2

編集:代わりに達成したい目標を明確にして含めるために、質問を書き直しました。

Akka を使用してメッセージを送信するシステムを構築しています。私はいくつかの小さなサービスを使用してそれを構築しています。すべてのメッセージがケース クラスとして存在する 1 つの共有コア ライブラリがあります。これらは、私のサービス間の契約を形成します。

私ができるようにしたいのは次のことですが、抽象クラス Message のパターン マッチングでコンパイル エラーが発生します。

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 msg@Message( 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 msg@Message( 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 )
4

1 に答える 1

0

探しているのはエクストラクタ ( unapplyunapplySeq)です。

ただし、それを実装する代わりに、設計を簡素化することをお勧めします。あなたの複数レベルの継承アプローチは混乱しすぎており、実際にその必要があるとは思いません。


抽象クラスを取り除くことで、少なくとも継承パターンが統一されました。ただし、設計の問題は残ります。それは、時期尚早に最適化することです。

正しいアプローチでは、最初に、これらの特定のケースでパターン マッチングが多すぎることに気付く必要があります。その場合にのみ、その解決策を探す必要があります。その逆ではありません。まだ直面していない問題を解決しようとせず、実際の問題に集中してください。ほとんどの場合、これらの最適化が実際に必要でなかったか、その時までにアプリが大幅に変更され、最適化の問題全体が時代遅れになっていることが後でわかります。そのため、単純なものから始めて、必要な場合にのみ複雑なものにしてください。

于 2013-06-02T09:28:05.867 に答える