3

私は最近Scalaを学び始め、単純なローグライクゲームを作成するための小さなプロジェクトを開始しました。しかし、私はオブザーバーパターンを実装しようとして立ち往生しています。 この答えは主題に触れていますが、それを機能させる方法がわかりません。以下は、上記のリンク先の回答のコードです。私はコードの「this:S =>」の部分にほとんど戸惑っています。そこに何らかの関数が必要だと思いますが、よくわかりません。サブジェクト特性を拡張するクラスからタプルを返してもらいたいのですが。

trait Observer[S] {
 def receiveUpdate(subject: S);
}

trait Subject[S] {
 this: S =>
 private var observers: List[Observer[S]] = Nil
 def addObserver(observer: Observer[S]) = observers = observer :: observers

 def notifyObservers() = observers.foreach(_.receiveUpdate(this))
}
4

4 に答える 4

10

selfタイプと別のコード例については、Steveの回答を参照してください。

オブザーバーを使用したサンプルコードを次に示します。オブザーバーによって観察されるのはObservedAccountです。SubjectAccountReporter

trait Observer[S] {
    def receiveUpdate(subject: S);
}

trait Subject[S] { 
    this: S =>
    private var observers: List[Observer[S]] = Nil
    def addObserver(observer: Observer[S]) = observers = observer :: observers

    def notifyObservers() = observers.foreach(_.receiveUpdate(this))
}

class Account(initialBalance: Double) {
    private var currentBalance = initialBalance
    def balance = currentBalance
    def deposit(amount: Double)  = currentBalance += amount
    def withdraw(amount: Double) = currentBalance -= amount
}

class ObservedAccount(initialBalance: Double) extends Account(initialBalance) with Subject[Account] {
    override def deposit(amount: Double) = {
        super.deposit(amount)
        notifyObservers()
    }
    override def withdraw(amount: Double) = {
        super.withdraw(amount)
        notifyObservers()
    }
}


class AccountReporter extends Observer[Account] {
    def receiveUpdate(account: Account) =
        println("Observed balance change: "+account.balance)
}

実際の動作を見てみましょう。

scala> val oa = new ObservedAccount(100.0)
oa: ObservedAccount = ObservedAccount@3f947e20

scala> val ar = new AccountReporter
ar: AccountReporter = AccountReporter@6ea70a98

scala> oa.addObserver(ar)

scala> oa.deposit(40.0)
Observed balance change: 140.0

scala> oa.withdraw(40.0)
Observed balance change: 100.0
于 2012-11-18T06:57:50.650 に答える
3

ブライアンの答えに基づいて:私は別のObserver[S]特性を持つ必要はないと思います、単にS => Unit十分です:

trait Subject[S] {
  this: S =>
  private var observers: List[S => Unit] = Nil
  def addObserver(observer: S => Unit) = observers = observer :: observers
  def notifyObservers() = observers.foreach(_.apply(this))
}

class Account(initialBalance: Double) {
  private var currentBalance = initialBalance
  def balance = currentBalance
  def deposit(amount: Double) = currentBalance += amount
  def withdraw(amount: Double) = currentBalance -= amount
}

class ObservedAccount(initialBalance: Double) extends Account(initialBalance)
  with Subject[Account] {

  override def deposit(amount: Double) = {
    super.deposit(amount)
    notifyObservers()
  }
  override def withdraw(amount: Double) = {
    super.withdraw(amount)
    notifyObservers()
  }
}

class AccountReporter {
  def receiveUpdate(account: Account) =
    println("Observed balance change: " + account.balance)
}

object Main extends App {
  println("start app")
  val oa = new ObservedAccount(100.0)
  val ar = new AccountReporter
  oa.addObserver(ar.receiveUpdate _)
  oa.deposit(40.0)
  oa.deposit(60.0)
  println("stop  app")
}


/**
      a copy paste observer pattern scala mini-app
      sbt run should produce:
      [info] Running app.Main
      start app
      Observed balance change: 140.0
      Observed balance change: 200.0
      stop  app
  */
于 2012-11-19T10:11:41.133 に答える
2

Sorry to answer a question with a question. Have you read your answer here or the more interesting answer here and here? Someone should compile a reading list, if they haven't. Did Coursera have a reading list?

于 2012-11-18T01:58:03.253 に答える
1

これはScalaセルフタイプです(http://www.scala-lang.org/node/124を参照)。これは、特性Subject [S]のすべての具体的な実装もタイプSに準拠する必要があるという要件を表します。つまり、すべての観察可能なSubject[S]はそれ自体がSです。

これはオブザーバーパターンにとって合理的です。登録と通知のメソッドを持つ必要があるのはオブザーバブルサブジェクト自体であるため、Sのオブザーバーと一致するサブジェクト自体がSである必要があります。

于 2012-11-17T22:20:51.427 に答える