Imagine I have a trait:
trait A {
type Elem
def list(e: Elem): List[Elem]
}
Is it possible somehow to create an object that extends this twice?
I know you can't inherit the same trait twice, but it could (in certain circumstances) be possible to have something like:
trait B extends A
object Server extends A with B {
}
So, is it possible to somehow alias the members of trait A in B? E.g. so then in Server I could set A.Elem = Int, B.Elem = String and have scala use method overloading to call the appropriate list function?
My use case for this is I've built an HTTP endpoint that accepts a specific implementation of a form class. However, I want to allow it to handle several different form classes (e.g. DetailedRegistration, SimpleRegistration) and to reuse the relevant logic.
Related
I have case classes that extend a trait Token and a function that returns a list of instances created using the case class apply method with appropriate parameters.
The trait defines a property name that is overridden in each case class.
A unit test calls a method that returns a list of the case class instances and tries to assert that the resultant list is the same as an expected list. This works but the comparison between lists is order dependent and although I could change the expected list to match the order of the returned list this would make the test depend on the method implementation and that is not something I wish to do.
The solution appears to be to sort the lists on that name value defined in the trait as each instance of the case class has the same name.
I have tried several things, best results so far add the extends Ordering[Token] to the Token trait, compiles except for the list sort function where I get
No implicit Ordering defined for B
My compare function in the Token trait is
def compare(x: Token, y: Token): Int =
x.name.compareToIgnoreCase(y.name)
There may be a better way to ignore the order in the lists however I would like at least to understand what I am doing wrong here and get the sort working.
Do you have an implicit Ordering for Token? Something like this should work:
trait Token {
def name: String
}
object Token {
implicit val ord: Ordering[Token] = Ordering.by(_.name.toLowerCase)
}
I was trying to look into trait and object in scala when it seems like we can use trait and object to do a similar task.
What should be the guiding principles on when to use trait and when to use object?
Edit:
As many of you are asking for an example
object PercentileStats {
def addPercentile(df: DataFrame): DataFrame // implementation
}
trait PercentileStats {
def addPercentile(df: DataFrame): DataFrame // implementation
}
There is a Process class which can use the object
object Process {
def doSomething(df: DataFrame): DataFrame {
PercentileStats.addPercentile(df)
}
}
We can also make it use the trait
object Process with PercentileStats {
def doSomething(df: DataFrame): DataFrame {
addPercentile(df)
}
}
I think the real question here is Where do I put stand-alone functions?
There are three options.
In the package
You can put stand-alone functions in the outer package scope. This makes them immediately available to the whole package but the name has to be meaningful across the whole package.
def addPercentile(df: DataFrame): DataFrame // implementation
In an object
You can group stand-alone functions in an object to provide a simple namespace. This means that you have to use the name of the object to access the functions, but it keeps them out of the global namespace and allows the names to be simpler:
object PercentileStats {
def add(df: DataFrame): DataFrame // implementation
}
In a trait
You can group stand-alone functions in a trait. This also removes them from the package namespace, but allows them to be accessed without a qualifier from classes that have that trait. But this also makes the method visible outside the class, and allows them to be overridden. To avoid this you should mark them protected final:
trait PercentileStats {
protected final def addPercentile(df: DataFrame): DataFrame // implementation
}
Which is best?
The choice really depends on how the function will be used. If a function is only to be used in a particular scope then it might make sense to put it in a trait, otherwise the other options are better. If there are a number of related function then grouping them in an object makes sense. One-off functions for general use can just go in the package.
Object - is a class that has exactly one instance. It is created lazily when it is referenced, like a lazy val.
As a top-level value, an object is a singleton.
Traits - are used to share interfaces and fields between classes.
Classes and objects can extend while traits cannot be instantiated and therefore have no parameters.
So, it means that if you prefer singleton type implementation with no new instance happen then use Object but if you want to inherit implementation to other class or objects then you can use trait.
Traits: are equivalent to interfaces in Java. So you can use it to define public contracts like interfaces in Java. In addition, a trait can be used to share values (beside methods) between classes extends the trait.
Objects in Scala is actually quite flexible. Example use cases include:
singletons: If you think that your objects are singletons (exactly
one instance exists in the program), you can use object.
factory: for instance, companion object of a class can be used as factory for creating instances of the class.
to share static methods: for example, common utilities can be declared in one object.
You also have to consider how you would want to use / import it.
trait Foo {
def test(): String
}
object Bar extends Foo
import Bar._
Objects enable you to import rather than mix in your class.
It is a life saver when you want to mock - with scalamock - a class that mixes a lot of traits and expose more than 22 methods that you don't really need exposed in the scope.
In Scala, a type definition inside a class or trait can be accessed via Class#Type. A type definition inside an object can be accessed via Object.Type.
What are some of the use cases, caveats and gotchas of using one vs the other?
What is a good patten to use for many unrelated classes which, however, have the same type parameter? For example:
class ScanUser[T <: User] { ... }
class PrintUser[T <: User] { ... }
How can I avoid repeating the type parameter restriction and reuse code?
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.
Is there a way in scala to get list of all objects(by object I mean scalas object) that derive from specified abstract class?
something like that:
abstract class A
object B extends A //in different file
object C extends A //in different file
def findObjectsDerivingFromA(): Seq[A] //which will give result: Seq(B, C)
I know from here : Can I get a compile-time list of all of the case objects which derive from a sealed parent in Scala?
that it's possible with sealed base trait/class but in my case objects B and C will be pretty complex so I need to have them in different files.
edit:
I've changed method name because previous one was misleading.