2

次のコードが期待どおりに機能しない理由を説明してください。

アクターはメッセージを印刷していません

ありがとう。

class Base {
  def f() = { "This is Base" }
}

class Sub extends Base {
  override def f() = { "This is Sub" }
}

case class myCase(x: Base)

import scala.actors._

object myActor extends Actor {

  def act()
  {
    loop {
      react {
        case myCase(x) => x.f()
        case msg => "unknown"
      }
    }
  }

  def main(args: Array[String]): Unit = {
    this ! myCase(new Base)
    this ! myCase(new Sub)
  }
}
4

1 に答える 1

4

質問に答える

この問題は、継承やケースクラスとは何の関係もありません(これを反映するために、質問のタイトルを変更しました)。このコードは、次の2つの理由で何も出力しません。

  1. コードは実際にはprintln!を呼び出さないためです。交換:

    case myCase(x) => x.f()
    

    case myCase(x) => println( x.f() )
    
  2. あなたはあなたの俳優を始めないので。アクターが内部クラスである場合、あなたのプログラムはより理にかなっていると思います。

    object myActor extends App {
    
      class MyActor extends Actor {
        def act() {
          loop {
            react {
              ...             // <-- You need to print stuff
            }
          }
        }
      }
    
      val a = new MyActor
      a.start()             // <-- You need to start it
      a ! myCase(new Base)
      a ! myCase(new Sub)
    }
    

アドバイス:ケースクラスと継承

ただし、ケースクラスが存在する場合に継承を使用することは悪い考えであるというアドバイスを提供します。私は通常、特性で一般的な動作/状態を宣言するアプローチを使用します。

sealed trait Base {
  def f(): Unit
}

case class Sub() extends Base

なぜそれは悪い考えですか?さて、ケースクラスがあなたに与える契約の1つは、同等性の厳密な定義(つまり、equalshashCode実装)です。継承が存在する場合、これは誤解を招く可能性があります。つまり、コードはおそらく期待どおりに機能しません。次のことを考慮してください。

scala> abstract class Base { val x: Int }
defined class Base

scala> case class Sub(s: String) extends Base { val x = util.Random.nextInt(100) }
defined class Sub

ここで、2つのインスタンスを作成すると...

scala> Sub("Hey")
res2: Sub = Sub(Hey)

scala> Sub("Hey")
res3: Sub = Sub(Hey)

それらは同等です

scala> res2 == res3
res4: Boolean = true

しかし、彼らは同じ状態を持っていません

scala> res2.x
res5: Int = 28

scala> res3.x
res7: Int = 15

これがバグだと言っているのではないことに注意してください。ケースクラスのすべての状態が同等に含まれていると仮定しているため、コードにバグが発生する可能がある領域だと言っています。

于 2012-04-30T10:53:46.687 に答える