Can we define trait inside a object in scala - scala

I just started to learn scala and currently learning about Akka through this Learning Akka course
I'm confused about the code style, the author has created a trait inside a object.
object MusicController {
sealed trait ControllerMsg
case object Play extends ControllerMsg
case object Stop extends ControllerMsg
def props = Props[MusicController]
}
I understand that Scala object provides singleton ability and a way to define all static method in class through companion object.
Can anyone help me understanding this syntax ? Thanks

You will often see this with Actors. It is good practice to define the messages that an Actor responds to in its companion object, which happens here.
The sealed trait part isn't really necessary. You just often see this in Scala with case classes/objects. Also, being sealed means that you will get a warning if your match is not exhaustive when you pattern match on instances of it.

Related

What are the advantages or disadvantages of declaring function/method in companion objects versus declaring them in traits?

I am new to Scala and I now started a project in Scala and I see similar to the following construct:
trait SomeTrait extends SomeOtherStuff with SomeOtherStuff2
object SomeTrait {
def someFunction():Unit = { ??? }
}
I understand that for a class, companion objects hold methods that are used in a "static", like Factory methods in Java or something alike, but what about traits, why not put these methods in traits?
The first style is called mixin, it used to be somewhat popular back in the days.
It could be replaced by the following code:
object SomeOtherStuff {
def someMethod(): String
}
object SomeObj {
import SomeOtherStuff._
//now someMethod is available
def otherMethod(): String = someMethod + "!"
}
object Caller {
import SomeObj._
import SomeOtherStuff._
//utility methods from both objects are available here
}
Pros of mixins:
If SomeTrait extends 10 other mixins then extending this trait would allow to scrap 10 import statements
Cons of mixins:
1) creates unnecessary coupling between traits
2) awkward to use if the caller doesn't extend the mixin itself
Avoiding mixins for business-logic code is a safe choice.
Although I'm aware of 2 legitimate usecases:
1) importing DSLs
e.g. ScalaTest code :
class SomeSuite extends FunSuite with BeforeAndAfter {...}
2) working (as a library author) with implicit parameters:
e.g. object Clock extends LowPriorityImplicits
(https://github.com/typelevel/cats-effect/blob/master/core/shared/src/main/scala/cats/effect/Clock.scala#L127)
Another perspective to this is the OOP principle Composition Over Inheritance.
Pros of companion objects (composition):
composition can be done at runtime while traits are defined at compile time
you can easily have multiple of them. You don't have to deal with the quirks of multiple inheritance: say you have two traits that both have a method with the name foo - which one is going to be used or does it work at all? For me, it's easier to see the delegation of a method call, multiple inheritance tends to become complex very fast because you lose track where a method was actually defined
Pros of traits (mixins):
mixins seem more idiomatic to reuse, a class using a companion object of another class is odd. You can create standalone objects though.
it's cool for frameworks because it adds the frameworks functionality to your class without much effort. Something like that just isn't possible with companion objects.
In doubt, I prefer companion objects, but it always depends on your environment.

Akka, Generic ActorRef?

I'm rather new to Scala so this may be a trivial question. I'm trying to put together a simple project in Akka and I'm not sure how to handle a situation where I need to store a reference to an actor of a constrained type.
Let's assume I have an actor trait
trait MyActorTrait extends Actor
Then somewhere else I would like to define another trait with a member
def reference: ActorRef[MyActorTrait]
That obviously doesn't work since ActorRef doesn't care about the target actor's type (or does it?). Is there any way to constrain the reference to only accept references to actors that extend MyActorTrait?
By design, there is no way you can access the underlying Actor through ActorRef (or, pretty much, any other way). So, constraining the type like you describe is pointless, there would be absolutely no difference in what you can do with ActorRef[Foo] vs. ActorRef[Bar].
Not saying, this is a good thing (few things in Akka can be characterized that way IMO), but that's just the way it is.
The way you try to reference an actor in another actor is not right. Actors form a hierarchy. So it gives you a path to refer an actor. There are mainly three ways you could reference another actor using
Absolute Paths
context.actorSelection("/user/serviceA")
Relative Paths
context.actorSelection("../brother") ! msg
Querying the Logical Actor Hierarchy
context.actorSelection("../*") ! msg
You may have a look at the doc - https://doc.akka.io/docs/akka/2.5/general/addressing.html.
After some digging around I believe I've found a way.
First I create a trait which will preserve the actor type
trait TypedActorRef[T <: Actor] {
def reference: ActorRef
type t = T
}
Then implement a generic apply which instantiates a private case class extending the trait
object TypedActorRef {
private case class Ref[T <: Actor] (reference: ActorRef) extends TypedActorRef[T]
def apply[T <: Actor](actor: T) = {
Ref[T](actor.self)
}
}
With that I can keep a reference which is restricted an actor of the type I want.
trait OtherActor extends Actor
trait MyActor extends Actor
{
def otherActorsReference: TypedActorRef[OtherActor]
}
This seems OK to me, at least this seems not to upset the compiler, but I'm not sure if this solution prevents from creating other extensions of the TypedActorRef which may not respect the same constraints.

Importing Scala companion object in file where it is defined

I have a ThisThing.scala file containing:
class ThisThing() extends BaseThing[ThisEvent, ThisState]
object ThisThing {
sealed trait ThisEvent
case class Load(uuid: UUID) extends ThisEvent
case object Stop extends ThisEvent
sealed trait ThisState
case object Loading extends ThisState
case object Loaded extends ThisState
}
Where ThisThing needs to be parameterized by the types of event and state it handles. This requires also having an import:
import ThisThing._
Which feels really strange, to have to import something from the same file. I'm guessing I'm doing something non idiomatic and that there is a better way to structure it?
It's a bit strange, but in principle valid.
It's non-idiomatic, because you are trying to hide ThisEvent and ThisState inside ThisThing's companion object, but at the same time you expose these types in the signature of ThisThing ... extends BaseThing[ThisEvent, ThisState].
The problem is that not only you, but also every user of ThisThing will have to unpack ThisThings companion object in order to write down the type BaseThing[ThisEvent, ThisState]:
// much later, in someone else's code in a galaxy far, far away
import foo.bar.baz.ThisThing.{ThisEvent, ThisState} // awkward to use!
val t: BaseThing[ThisEvent, ThisState] = new ThisThing
So... If you think that someone will want to access ThisEvent and ThisState later, then move them out of the ThisThing companion.
If you think that nobody should even know that ThisThing is actually a
BaseThing[X, Y], then you have an abstraction leak anyway, and you could handle it by declaring ThisThing as a trait, and then implementing a concrete class that extends both ThisThing and BaseThing inside the ThisThing's companion object, so that BaseThing does not leak to the outside.
To summarize, it's one of two scenarios:
Scenario 1: BaseThing[ThisEvent, ThisState] should be visible from the outside. In this case, ThisEvent and ThisState are buried a bit too deep in the companion object, and are therefore awkward to access.
Scenario 2: BaseThing[ThisEvent, ThisState] is an abstraction leak.
Just a random guess: If you just want to parameterize something like an Akka FSM, leave it as it is now. I think it's common, because nobody outside should really care how an actor is actually implemented. It's impossible to obtain an explicit reference to ThisThing anyway, because all you ever see are the ActorRefs, so that the actual instance is hidden. In this case the "abstraction leak" isn't too critical, because nobody ever sees an actual instance of your FSM.

Instantiating all classes that extend trait in Scala

So I'm building a library, and the problem I have is as follows:
I have a trait, such as
package my.library
trait Animal {
def randomFunctions
}
What I need to know is all the classes the consumer code has, that extend/implement said trait, such as
package code.consumer
case class Cat extends Animal
case class Dog extends Animal
So in summary: inside my library (which has the trait) I need to find out all classes (in consumer code) that extend/implement the trait.
I finally solved this by using reflections (https://github.com/ronmamo/reflections) with the following little snippet:
val reflection = new Reflections()
reflection.getSubTypesOf(classOf[Animal])
An option would be to use a sealed trait. This forces all implementations of the trait to reside in the same file as the trait was defined.
This would break your separation of consumer and library code but you would be sure to get all implementations.
The only other option I can think of is to use an IDE, like IntelliJ which has an option to find all implementation based on given trait.

Scala: Dispatch

I'm willing how to implement an extensible dispatch mechanism in Scala.
For example:
I have a trait called Sender (with a method 'send') and a bunch of classes that implement that trait (MailSender, IPhoneSender, AndroidSender). On top of them there is a class which implements the same trait but dispatches the message to the above senders depending the type of the message.
I know I can use pattern matching, but my problem with that approach is about extensibility: If someone wants to add another sender (i.e. WindowsPhoneSender), he must add a new case to the pattern matching method (thus breaking the open-closed principle). I don't want developers to modify the library's code, so I need this to be as extensible as possible.
I thought about a chain of responsibility approach (in Java I would do that), but is there a better way in Scala? (My knowledge in Scala is limited, but I know the Scala compiler does a lot of magical things)
Thanks!
It would be clearer if you gave a more concrete use case, but you might be looking for the typeclass pattern:
case class AndoidMessage()
case class WindowsMessage()
trait Sender[M]{
def send(message: M)
}
implicit object AndroidSender extends Sender[AndroidMessage]{...}
implicit object WindowsSender extends Sender[AndroidMessage]{...}
def mySendMethod[M: Sender](message: M) = {
// use the implicit Sender[M] to send the message
}
//AndroidSender is resolved implicitly
mySendMethod(new AndroidMessage())
//third party can define their own message and their own
//implicit sender for it (perhaps in a companion object
//so it's resolved automatically)
case class BeosMessage()
object BeosMessage{
implicit object BMSender extends Sender[BeosMessage]{...}
}