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.
Related
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.
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.
I am a beginner in Scala and was playing around to learn more about Abstract data types. I defined the following definition to replicate Option type:
sealed abstract class Maybe[+A](x:A)
case object Nothing extends Maybe[Nothing](Nothing)
case class Just[A](x:A) extends Maybe[A](x)
But I encountered the following error.
found : Nothing.type
required: Nothing
case object Nothing extends Maybe[Nothing](Nothing)
How do I pass Nothing instead of Nothing.type?
I referred to the following question for hints:
How to extend an object in Scala with an abstract class with constructor?, but it was not helpful.
Maybe more like this. Your Nothing shouldnt have a value, just the type. Also people usually use traits instead of abstract classes.
sealed trait Maybe[+A]
case object None extends Maybe[Nothing]
case class Just[A](x:A) extends Maybe[A]
You probably shouldnt create your own Nothing, thats going to be confusing, you will confuse yourself and the compiler about if you are referring to your one, or the one at the bottom of the type hierarchy.
As mentioned by Stephen, the correct way to do this would be not to have trait and not an abstract class, however, I thought it might be informative to explain why the current methodology fails and how to fix it.
The main issue is with this line:
case object Nothing extends Maybe[Nothing](Nothing)
First thing (as mentioned) you shouldn't call your object Nothing. Secondly, you set the object to extend Maybe[Nothing]. Nothing can't have any actual values so you can't use it as an object. Also, you can't use the object itself as the constructor parameter because that would cause a cyclic behavior.
What you need is to have a bottom type (i.e. a type which all A have in common) and an object of that type. Nothing is a bottom type but has no objects.
A possible solution is to limit yourself to AnyRef (i.e. nullable objects) and use the Null bottom type which has a valid object (null):
sealed abstract class Maybe[+A <: AnyRef](x:A)
case object None extends Maybe[Null](null)
This is a bit of clarification for Assaf Mendelson's answer, but it's too big for a comment.
case object Nothing extends Maybe[Nothing](Nothing)
Scala has separate namespaces for types and values. Nothing in case object Nothing is a value. Nothing in Maybe[Nothing] is a type. Since you didn't define a type called Nothing, it refers to the automatically imported scala.Nothing and you must pass a value of this type as an argument. By definition it has no values but e.g. case object Nothing extends Maybe[Nothing](throw new Exception) would compile, as the type of throw expressions is Nothing. Instead you pass the value Nothing, i.e. the same case object you are defining; its type is written as Nothing.type.
How do I pass Nothing instead of Nothing.type?
It seems like there is no way to do so.
As it says at http://www.scala-lang.org/api/2.9.1/scala/Nothing.html:
there exist no instances of this type.
I've encountered something which I don't quite understand, so lets begin:
If i've got this object:
case object StartMessage
written like above and then obtain its references from two different classes:
class Test2 {
def print(){
println(Integer.toHexString(System.identityHashCode(StartMessage)))
}
}
class Test1 {
def print(){
println(Integer.toHexString(System.identityHashCode(StartMessage)))
}
}
as expected result is:
object ActorMain extends App{
new Test1().print()//45c8e616
new Test2().print()//45c8e616
}
But when i change case object to pack it in trait:
trait model{
case object StartMessage
}
then my classes will have declaration like:
class Test1 extends model{
class Test2 extends model{
I receive:
45c8e616
7d417077
*1. Could you explain it to me? I was thinking that objects are one in whole application, so when i create Trait with objects in it, every time i will extends (use "with") those trait, the object will be the same, not somewhat trait scoped.
*2. Is there another way to obtain functionality to "add" same objects only with extending trait to concrete classes, and not make them visible for whole application? Case is to have cleaner code with possibility to "mark" classes as "they use those objects, while others don't"
Objects defined within trait are singletons given trait scope. It is actually referring to the instance of a trait, not the trait itself. And the resulting behavior is the one that you see -> objects are created per instance. And this leads to the conclusion that you cannot define objects by extending traits to be shared across different classes. There was similar question on SO some time ago, I'll try to find it later.
Personally I would go for passing to classes some sort of a context to provide shared resources.
I get the coding in that you basically provide an "object SomeClass" and a "class SomeClass" and the companion class is the class declaration and the object is a singleton. Of which you cannot create an instance. So... my question is mostly the purpose of a singleton object in this particular instance.
Is this basically just a way to provide class methods in Scala? Like + based methods in Objective-C?
I'm reading the Programming in Scala book and Chapter 4 just talked about singleton objects, but it doesn't get into a lot of detail on why this matters.
I realize I may be getting ahead of myself here and that it might be explained in greater detail later. If so, let me know. This book is reasonably good so far, but it has a lot of "in Java, you do this", but I have so little Java experience that I sort of miss a bit of the points I fear. I don't want this to be one of those situations.
I don't recall reading anywhere on the Programming in Scala website that Java was a prerequisite for reading this book...
Yes, companion singletons provide an equivalent to Java's (and C++'s, c#'s, etc.) static methods.
(indeed, companion object methods are exposed via "static forwarders" for the sake of Java interop)
However, singletons go a fair way beyond this.
A singleton can inherit methods from other classes/traits, which can't be done with statics.
A singleton can be passed as a parameter (perhaps via an inherited interface)
A singleton can exist within the scope of a surrounding class or method, just as Java can have inner classes
It's also worth noting that a singleton doesn't have to be a companion, it's perfectly valid to define a singleton without also defining a companion class.
Which helps make Scala a far more object-oriented language that Java (static methods don't belong to an object). Ironic, given that it's largely discussed in terms of its functional credentials.
In many cases we need a singleton to stand for unique object in our software system.
Think about the the solar system. We may have following classes
class Planet
object Earth extends Planet
object Sun extends Planet
object is a simple way to create singleton, of course it is usually used to create class level method, as static method in java
Additional to the given answers (and going in the same general direction as jilen), objects play an important role in Scala's implicit mechanism, e.g. allowing type-class-like behavior (as known from Haskell):
trait Monoid[T] {
def zero:T
def sum(t1:T, t2:T):T
}
def fold[T](ts:T*)(implicit m:Monoid[T]) = ts.foldLeft(m.zero)(m.sum(_,_))
Now we have a fold-Function. which "collapses" a number of Ts together, as long as there is an appropriate Monoid (things that have a neutral element, and can be "added" somehow together) for T. In order to use this, we need only one instance of a Monoid for some type T, the perfect job for an object:
implicit object StringMonoid extends Monoid[String] {
def zero = ""
def sum(s1:String, s2:String) = s1 + s2
}
Now this works:
println(fold("a","bc","def")) //--> abcdef
So objects are very useful in their own right.
But wait, there is more! Companion objects can also serve as a kind of "default configuration" when extending their companion class:
trait Config {
def databaseName:String
def userName:String
def password:String
}
object Config extends Config {
def databaseName = "testDB"
def userName = "scott"
def password = "tiger"
}
So on the one hand you have the trait Config, which can be implemented by the user however she wants, but on the other hand there is a ready made object Config when you want to go with the default settings.
Yes, it is basically a way of providing class methods when used as a companion object.