简体   繁体   中英

Scala actor apparently not receiving messages

Could you please explain why the following code is not working as expected.

The actor is not printing the message

Thanks.

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)
  }
}

Answering the question

The problem has nothing whatsoever to do with inheritance or case classes (I have re-titled the question to reflect this). The code does not print anything for two reasons:

  1. Because your code does not actually make any calls to println ! Replace:

     case myCase(x) => xf() 

    with

     case myCase(x) => println( xf() ) 
  2. Because you do not start your actor . I think your program would make more sense if the actor were an inner class:

     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) } 

Advice: case classes and inheritance

I would, however, offer the advice that using inheritance in the presence of case classes is a bad idea . I usually use the approach of declaring common behaviour/state in a trait:

sealed trait Base {
  def f(): Unit
}

case class Sub() extends Base

Why is it a bad idea? Well, one of the contracts that case-classes give you is a rigid definition of equivalence (that is, an equals and hashCode implementation). In the presence of inheritance, this could well be misleading . That is, your code will probably not do what you expect. Consider the following;

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

Now if I create 2 instances...

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

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

They are equivalent

scala> res2 == res3
res4: Boolean = true

But they do not have the same state

scala> res2.x
res5: Int = 28

scala> res3.x
res7: Int = 15

Note, I am not saying this is a bug. I'm just saying it's an area where you might find that you introduce a bug in your code because you have made the assumption that any state of the case class is included in its equivalence.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM