I'm quite new to Scala, but I'm trying to implement the following situation. Suppose I have a trait:
trait SomeTrait {
def kakaw
}
And two Scala objects that extend it:
object SampleA extends SomeTrait {
def kakaw = "Woof"
}
object SampleB extends SomeTrait {
def kakaw = "Meow"
}
What I'd like to do is call one of these two object functions based on a parameterized function call. For example (and I know this is the furthest thing from correct):
class SomeOther {
def saySomething[T] = T.kakaw
}
So I can do something like:
val s = new SomeOther
s.saySomething[SampleA]
Is this at all possible in Scala?
& scala
Welcome to Scala version 2.8.1.final (Java HotSpot(TM) 64-Bit Server VM, Java 1.6.0_23).
Type in expressions to have them evaluated.
Type :help for more information.
scala> trait SomeTrait {
| def kakaw : String
| }
defined trait SomeTrait
scala> class SampleA extends SomeTrait {
| def kakaw = "Woof"
| }
defined class SampleA
scala> implicit val sampleA = new SampleA
sampleA: SampleA = SampleA#42c71191
scala> class SampleB extends SomeTrait {
| def kakaw = "Meow"
| }
defined class SampleB
scala> implicit val sampleB = new SampleB
sampleB: SampleB = SampleB#53601a4f
scala> class SomeOther {
| def saySomething[ T <: SomeTrait](implicit target : T) = target.kakaw
| }
defined class SomeOther
scala> val s = new SomeOther
s: SomeOther = SomeOther#5947e54e
scala> s.saySomething[SampleA]
res0: String = Woof
It’s a bit confusing because you’ll need to have an instance of your type to act on. Just passing a type may make the compiler happy but you certainly want to make sure that you supply the very instance of some type you want to work with.
(Considering singleton objects there may be a work around using implicit evidence parameters for that, but I wouldn’t do that unless really needed.)
So, in your case why don’t you just say
class SomeOther {
def saySomething(obj: SomeTrait) = obj.kakaw
}
val s = new SomeOther
s.saySomething(SampleA)
Related
Let's say I have some trait:
trait A[T] { def foo: T }
A class which extends it:
class B[T](t: T) extends A[T] { def foo = t }
And a subtrait of the parent trait:
trait C[T] extends A[T]
I want to mix C in with B.
val foo = new B("foo") with C[String]
This works fine, but I'd rather not need to specify the type parameter again, since B is already of type A[String]. However, I recognize Scala doesn't support the following:
val foo = new B("foo") with C
My question is where there's some other mechanism in the type system to support not having to specify the type parameters when C is mixed in. What I was thinking of was something as follows:
trait C {
self: A[T] => ...
}
One would think this kind of thing would fix what C could be mixed into. However, it isn't valid Scala. Something like:
trait C {
type T
self: A[T] =>
}
does not work either.
You can do this using an abstract type:
trait A {
type AT
def foo: AT
}
class B[T](t: T) extends A {
type AT = T
def foo = t
}
trait C extends A
val foo = new B("foo") with C
The definition is a bit more verbose, but your requirement of not having to type T again is satisfied.
How about this:
scala> trait C {
| self: A[_] =>
| }
defined trait C
scala> val foo = new B("foo") with C
foo: B[String] with C = $anon$1#f2df380
scala> foo.foo
res16: String = foo
How can I implement the following psuedocode in Scala using reflection?
I require this for the purposes of looking-up a generic type from Guice:
trait Foo[A]
class FooInt extends Foo[Int]
class FooString extends Foo[String]
bind(new TypeLiteral<Foo<Int>>() {}).to(FooInt.class);
def fooTypeLiteral(paramA: Class[_]): TypeLiteral[_] = ???
val foo = injector.getInstance(fooTypeLiteral(classOf[Int])
// foo: FooInt
Note: I do not have access to the type of A at compile time, hence the _. The entire solution needs to be performed reflectively (e.g. I cannot have parameterizeFoo[A : ClassTag](...)).
You could try to create a ParameterizedType and pass it to the factory method of the TypeLiteral:
def fooTypeLiteral(paramA: Class[_]): TypeLiteral[_] = {
TypeLiteral.get(new java.lang.reflect.ParameterizedType() {
def getRawType = classOf[Foo[_]]
def getOwnerType = null
def getActualTypeArguments = Array(paramA)
})
}
If you have only a finite number of Foo implementations, you could try this:
trait Foo[A]
class FooInt extends Foo[Int]
class FooString extends Foo[String]
val TLFI = new TypeLiteral[Foo[Int]](){}
val TLFS = new TypeLiteral[Foo[String]](){}
bind(TLFI).to(FooInt.class);
bind(TLFS).to(FooString.class);
def fooTypeLiteral(c: Class[_]): TypeLiteral[_] = {
if (c == classOf[Int]) TLFI
else if (c == classOf[String]) TLFS
else throw new Error
}
Both Scala and Java compilers implement generics with type erasure. This means that all type information for sub-types of generics is lost when the source code is converted to JVM byte code. If the generic class itself does not hold ClassTag or similar, embedded information, then you cannot get the class at run time.
I need to write a generic class that can only allow the types Long,Double in place of [V]
class DummyGenericClass[V](data:Seq[V])
Also, there will be an implementation difference based on the type. I want to do something like
val typ = if (V is Long) "x" else "y"
What is the recommended/best practice in scala to write such code?
You can achieve it using sealed trait, which limits possible implementations to those that are defined in the same file:
sealed trait DummyGenericClass[V] {
val data: Seq[V]
val typ: String
}
class LongClass(val data: Seq[Long]) extends DummyGenericClass[Long] {
val typ = "x"
}
class DoubleClass(val data: Seq[Double]) extends DummyGenericClass[Double] {
val typ = "y"
}
If you want to have a generic constructor for DummyGenericClass the type safe way to do it is to use typeclass combined with factory pattern:
object DummyGenericClass {
trait Factory[T] {
def create(seq: Seq[T]): DummyGenericClass[T]
}
object Implicits {
implicit val longProvider =
new Factory[Long] {
def create(seq: Seq[Long]) = new LongClass(seq)
}
implicit val doubleProvider =
new Factory[Double] {
def create(seq: Seq[Double]) = new DoubleClass(seq)
}
}
def apply[T: Factory](seq: Seq[T]) = implicitly[Factory[T]].create(seq)
}
Which you can use the following way:
import DummyGenericClass.Implicits._
val foo = DummyGenericClass(Seq.empty[Long])
val bar = DummyGenericClass(Seq.empty[Double])
// Won't compile:
val baz = DummyGenericClass(Seq.empty[String])
The other way, that doesn't require defining a typeclass to create DummyGenericClass instances, is to pass ClassTag bound to T in the factory method. However this solution is not recommended since it's not a type safe way, as it allows one to pass type argument that is not supported and will fail at runtime.
If you want to have a generic method that uses this constructor, you have to add DummyGenericClass.Factory context bound to that method too:
def add[T: DummyGenericClass.Factory]
(a: DummyGenericClass[T], b: DummyGenericClass[T]) =
DummyGenericClass(a.data ++ b.data)
import DummyGenericClass.Implicits._
add(DummyGenericClass(Seq(1.0)), DummyGenericClass(Seq(2.0)))
The type class pattern in Scala involves defining a trait such as:
trait Show[T] {
def show(obj: T): String
}
Then you can define instantiations of this type class as such:
object Show {
implicit val string = new Show[String] {
def show(obj: String): String = obj
}
implicit object BooleanShow extends Show[Boolean] {
def show(obj: Boolean): String = obj.toString
}
}
The advantage of defining these instantiations for basic types in the companion object is that they are automatically in scope whenever the type class is concerned (roughly).
Functionally it would appear defining the instantiation as an implicit val or an implicit object does not change much.
Is there a difference? Is one way better than the other?
There is actually more than the type names between val and object.
You know, object in Scala is something like a singleton in Java.
Maybe you thought that both string and BooleanShow are in an object not a class so they have no difference, but that's not true.
They are val and object no matter what.
Try this in Scala REPL.
trait Show[T] {
def show(obj: T): String
}
object Show {
println("!! Show created")
implicit val string = new Show[String] {
println("!! string created")
def show(obj: String): String = obj
}
implicit object BooleanShow extends Show[Boolean] {
println("!!BooleanShow created")
def show(obj: Boolean): String = obj.toString
}
}
If only the definition is done, then no printlns are executed afterwards, since Show is a singleton in effect. It's not created yet.
Next, execute Show in Scala REPL.
scala> Show
!! Show created
!! string created
res0: Show.type = Show$#35afff3b
You see, printlns in Show and Show.string were called, but the one in Show.BooleanShow was not.
You can execute Show.BooleanShow next in Scala REPL.
scala> Show.BooleanShow
!!BooleanShow created
res1: Show.BooleanShow.type = Show$BooleanShow$#18e419c5
Show.BooleanShow was initialized at last. It is a singleton, so it is lazy.
Basically, your question is the same as val and object inside a scala class? except that your val and object are defined in an object, but the linked question tries to find differences val and object defined in a class and the method in val uses reflection (but yours uses overriding, so no reflection is involved). implicit basically does not make difference in what they are.
I think you already know the difference between class and object. Further information can be found in the linked question.
Since they say always to use explicit types for implicits, prefer val over object.
Compare Why can't Scala find my typeclass instance defined implicitly in the companion object, when the typeclass is not in a dedicated source file? where it makes a difference.
Make it lazy if necessary.
Elaboration:
scala> trait T
defined trait T
scala> object X { implicitly[T] ; object O extends T }
<console>:8: error: could not find implicit value for parameter e: T
object X { implicitly[T] ; object O extends T }
^
scala> object X { implicitly[T] ; implicit object O extends T }
<console>:8: error: could not find implicit value for parameter e: T
object X { implicitly[T] ; implicit object O extends T }
^
scala> object X { implicitly[O.type] ; implicit object O extends T }
defined object X
scala> object X { implicitly[T] ; implicit object O extends T ; implicit def y = O }
<console>:8: error: could not find implicit value for parameter e: T
object X { implicitly[T] ; implicit object O extends T ; implicit def y = O }
^
scala> object X { implicitly[T] ; implicit object O extends T ; implicit def y: T = O }
defined object X
The inferred type of O is the singleton type O.type.
With val x = new X { } you are creating an anonymous subclass of X, whereas with object x extends X you create a "proper" subclass. I would think that the overhead of an object is minimal, and as #applicius points out, it has proper name. Therefore I suggest to go for the object in this case.
Given a trait MyTrait:
trait MyTrait {
def doSomething = println("boo")
}
it can be mixed into a class with extends or with:
class MyClass extends MyTrait
It can also be mixed upon instantiating a new instance:
var o = new MyOtherClass with MyTrait
o.doSomething
But...can the trait (or any other if that makes a difference) be added to an existing instance?
I'm loading objects using JPA in Java and I'd like to add some functionality to them using traits. Is it possible at all?
I'd like to be able to mix in a trait as follows:
var o = DBHelper.loadMyEntityFromDB(primaryKey);
o = o with MyTrait //adding trait here, rather than during construction
o.doSomething
I have a idea for this usage:
//if I had a class like this
final class Test {
def f = println("foo")
}
trait MyTrait {
def doSomething = {
println("boo")
}
}
object MyTrait {
implicit def innerObj(o:MixTest) = o.obj
def ::(o:Test) = new MixTest(o)
final class MixTest private[MyTrait](val obj:Test) extends MyTrait
}
you can use this trait as below:
import MyTrait._
val a = new Test
val b = a :: MyTrait
b.doSomething
b.f
for your example code:
val o = DBHelper.loadMyEntityFromDB(primaryKey) :: MyTrait
o.doSomething
I hope this can help you.
UPDATED
object AnyTrait {
implicit def innerObj[T](o: MixTest[T]):T = o.obj
def ::[T](o: T) = new MixTest(o)
final class MixTest[T] private[AnyTrait](val obj: T) extends MyTrait
}
but this pattern has some restrict, you can't use some implicit helper method that defined already.
val a = new Test
a.f
val b = a :: AnyTrait
b.f1
b.f
val c = "say hello to %s" :: AnyTrait
println(c.intern) // you can invoke String's method
println(c.format("MyTrait")) //WRONG. you can't invoke StringLike's method, though there defined a implicit method in Predef can transform String to StringLike, but implicit restrict one level transform, you can't transform MixTest to String then to StringLike.
c.f1
val d = 1 :: AnyTrait
println(d.toLong)
d.toHexString // WRONG, the same as above
d.f1
An existing runtime object in the JVM has a certain size on the heap. Adding a trait to it would mean altering its size on the heap, and changing its signature.
So the only way to go would be to do some kind of transformation at compile time.
Mixin composition in Scala occurs at compile time. What compiler could potentially do is create a wrapper B around an existing object A with the same type that simply forwards all calls to the existing object A, and then mix in a trait T to B. This, however, is not implemented. It is questionable when this would be possible, since the object A could be an instance of a final class, which cannot be extended.
In summary, mixin composition is not possible on existing object instances.
UPDATED:
Related to the smart solution proposed by Googol Shan, and generalizing it to work with any trait, this is as far as I got. The idea is to extract the common mixin functionality in the DynamicMixinCompanion trait. The client should then create a companion object extending DynamicMixinCompanion for each trait he wants to have the dynamic mixin functionality for. This companion object requires defining the anonymous trait object gets created (::).
trait DynamicMixinCompanion[TT] {
implicit def baseObject[OT](o: Mixin[OT]): OT = o.obj
def ::[OT](o: OT): Mixin[OT] with TT
class Mixin[OT] protected[DynamicMixinCompanion](val obj: OT)
}
trait OtherTrait {
def traitOperation = println("any trait")
}
object OtherTrait extends DynamicMixinCompanion[OtherTrait] {
def ::[T](o: T) = new Mixin(o) with OtherTrait
}
object Main {
def main(args: Array[String]) {
val a = "some string"
val m = a :: OtherTrait
m.traitOperation
println(m.length)
}
}
I usually used a implicit to mix in a new method to an existing object.
See, if I have some code as below:
final class Test {
def f = "Just a Test"
...some other method
}
trait MyTrait {
def doSomething = {
println("boo")
}
}
object HelperObject {
implicit def innerObj(o:MixTest) = o.obj
def mixWith(o:Test) = new MixTest(o)
final class MixTest private[HelperObject](obj:Test) extends MyTrait
}
and then you can use MyTrait method with an already existing object Test.
val a = new Test
import HelperObject._
val b = HelperObject.mixWith(a)
println(b.f)
b.doSomething
in your example, you can use like this:
import HelperObject._
val o = mixWith(DBHelper.loadMyEntityFromDB(primaryKey));
o.doSomething
I am thinking out a prefect syntax to define this HelperObject:
trait MyTrait {
..some method
}
object MyTrait {
implicit def innerObj(o:MixTest) = o.obj
def ::(o:Test) = new MixTest(o)
final class MixTest private[MyTrait](obj:Test) extends MyTrait
}
//then you can use it
val a = new Test
val b = a :: MyTrait
b.doSomething
b.f
// for your example
val o = DBHelper.loadMyEntityFromDB(primaryKey) :: MyTrait
o.doSomething
What about an implicit class? It seems easier to me compared to the way in the other answers with a final inner class and a "mixin"-function.
trait MyTrait {
def traitFunction = println("trait function executed")
}
class MyClass {
/**
* This inner class must be in scope wherever an instance of MyClass
* should be used as an instance of MyTrait. Depending on where you place
* and use the implicit class you must import it into scope with
* "import mypackacke.MyImplictClassLocation" or
* "import mypackage.MyImplicitClassLocation._" or no import at all if
* the implicit class is already in scope.
*
* Depending on the visibility and location of use this implicit class an
* be placed inside the trait to mixin, inside the instances class,
* inside the instances class' companion object or somewhere where you
* use or call the class' instance with as the trait. Probably the
* implicit class can even reside inside a package object. It also can be
* declared private to reduce visibility. It all depends on the structure
* of your API.
*/
implicit class MyImplicitClass(instance: MyClass) extends MyTrait
/**
* Usage
*/
new MyClass().traitFunction
}
Why not use Scala's extend my library pattern?
https://alvinalexander.com/scala/scala-2.10-implicit-class-example
I'm not sure what the return value is of:
var o = DBHelper.loadMyEntityFromDB(primaryKey);
but let us say, it is DBEntity for our example. You can take the class DBEntity and convert it to a class that extends your trait, MyTrait.
Something like:
trait MyTrait {
def doSomething = {
println("boo")
}
}
class MyClass() extends MyTrait
// Have an implicit conversion to MyClass
implicit def dbEntityToMyClass(in: DBEntity): MyClass =
new MyClass()
I believe you could also simplify this by just using an implicit class.
implicit class ConvertDBEntity(in: DBEntity) extends MyTrait
I particularly dislike the accepted answer here, b/c it overloads the :: operator to mix-in a trait.
In Scala, the :: operator is used for sequences, i.e.:
val x = 1 :: 2 :: 3 :: Nil
Using it as a means of inheritance feels, IMHO, a little awkward.