I want to extend a trait from Scala object and override those methods which are in trait. So my doubt is those methods will become static to that Object
or instance methods, and is this good approach to extend from trait to Scala Object. Please help on this
trait A{
def show:Unit
}
object B extends A{
override def show(): Unit = {
println("inside Object")
}
}
There are no static methods in Scala. object can indeed extend a trait. Overriden methods, like show, do not become static methods, instead they belong to a single instance of B.type. This is the singleton pattern provided by Scala's object definition facility.
Try the following in Scala REPL:
object B
B
It should output something like
res0: B.type = B$#5688722f
Note how the value B has type B.type, so B is just a value/instance, nothing to do with statics.
Hm, I think a common example/usecase of what you've just described is extending the App trait and overriding the main definition.
object test extends App
{
override def main (args: Array[String]): Unit = {
println("Hello, let's get started")
}
}
In general though, why don't you define the class itself to extend the trait?
If you are going to instantiate new instances of B using B() (instead of new B()) it makes sense to do this.
trait A{
def show:Unit
}
object B { // companion aka singleton object
def apply(){
...
}
}
class B extends A{
override def show(): Unit = {
println("inside Object")
}
}
Related
I am new to scala. I don't understand scala traits properly. I have read it is similar to java interfaces but the methods need not be abstract. But how can I declare a scala trait and instantiate it in the following code. BTW, the following code is working fine.
trait fooable {
def foo: Unit = {
println("This is foo")
}
}
object Main {
def main(args: Array[String]): Unit = {
println("This is morking")
val foo = new fooable{}
foo.foo
}
}
Output -
This is morking
This is foo
Thanks in advance.
Scala traits are more general than both Java interfaces and abstract classes.
You can use a trait as an interface, you can use it to store some implementation, you can use it simply to define a common super-type:
trait Message
case class Text(text: String) extends Message
case class Data(data: ByteString) extends Message
Multiple traits can be 'mixed in' a class:
class MyClass extends TraitA with TraitB with TraitC
where any conflict with identically named methods is resolved by the simple rule: the last trait takes precedence. This code:
trait TraitA { def print() { println("A") } }
trait TraitB { def print() { println("B") } }
trait TraitC { def print() { println("C") } }
new MyClass.print()
will print "C".
Scala traits can't be instantiated. You are creating an anonymous class in you example. If you add an abstract method to your trait it will not compile.
Unrelated note:
It is a good practice to write braces "()" in methods with side effects. Your method foo has a side effect: it prints something. So you should write "foo()".
When you instantiate a trait you create an instance of an anonymous class that extends that trait it works the same way as creating anonymous classes of interfaces in java. If you had any unimplemented methods in the trait fooable the compiler would've forced you to implement them on spot when you created your anonymous class.
Indeed your code should work fine and output the same result you mentioned. However the important point to note here is TRAIT CAN NEVER EVER be instantiated. Its the same concept that Java interface can never ever be instantiated.
When scala compiler notice the code foo = new fooable{}, It internally creates an anonymous class which extends your fooable trait and thus it inherits foo() method due to inheritance. See following code snippet:
scala> val foo = new fooable{}
foo: fooable = $anon$1#277c0f21
Thus when you call foo.foo, At runtime it invokes a anonymous's class(i.e. $anon$1#277c0f21) inherited method foo().
The same understanding is true in case of Java as well, Following is perfectly legal java code:
Runnable r = new Runnable() {
public void run() {
System.out.println(" Cat");
}
};
r.run()
Happy learning !
An Scala Trait is abstract and can't be instantiated. In the code above its instantiated as
val foo = new fooable{}
and NOT as
val foo = new fooable()
The curly braces created some anonymous class which is not fooable but an empty one
What are Traits?
Traits are similar to interfaces in any other language. Scala allows traits to be instantiate during definition as well as during construction. For example if we have a trait and a abstract class
trait testTrait {
}
abstract class BaseClass {}
class Derive extends BaseClass with testTrait {
}
// ---------------------- OR----------------------
// Traits can be used during instantiation
class Derive extends BaseClass {
}
val classInst = new Derive with testTrait
Traits can also be chained using multiple with trait
In Scala I want to return a instance of a class for a method defined in a trait which uses generics, the code example I have is this:
File 1
package packOne
import packTwo.A
trait MyTrait[T <: MyTrait[T <: A]] {
def otherFunct(): String
def funct[T <: A](): T
}
File 2
package packTwo
import packOne.MyTrait
abstract class A(someParameter: String) {}
class B(someParameter: String) extends A(someParameter) {}
object B extends MyTrait[B] { // <--- the B inside MyTrait here is the class not the object, or at least that is what I want
def otherFunct(): String = "Hello"
def funct[B](): C = new B("hi") // <--- I think here is the key
}
basically what I want is an interface that have method to return a concrete implementation of class A, in an implementing object (which happen to be a companion object for a class extending A).
Why do I want that to be on an object?, is because I want to call that method without the need of an instance (like an static method in java), so that I can call B.funct() and have an instance of B class kind of like a factory method, for other classes extending A for example a call to X.funct will return an instance of class X.
I have tried to remove the generic type from the function definition except on the return type of the function and just leave it in the trait definition (like def funct(): T) but that does not work either.
I am quite new to Scala so if you could explain it for dummies and avoid complex scala unique concepts I would appreciate
How about simply:
trait A
class B(someParameter: String) extends A
trait MyTrait[T <: A] {
def otherFunct: String //Parentheses on parameterless methods with no side effects and no serious computation are generally unidiomatic in Scala
def funct: T //Note, no generic parameter on this method
}
object B extends MyTrait[B] {
def otherFunct = "Hello"
def funct = new B("hi")
}
And then:
B.funct //returns a new `B`
The apply method is often used in this factory style (e.g. Seq.apply() which is equivalent to Seq())
I'm looking for a way to define a method that returns a type T where T = the type of the subclass.
I know I could possibly do this using abstract types, but dislike the overhead of having to redefine T for each subclass.
Some sample code:
object Helper {
def help[A <: MyClass](cls: A): Option[A] = { cls.foo() map { _.asInstanceOf[A] } }
}
class MyClass {
type T <: MyClass
def foo(): Option[T] = Some(this.asInstanceOf[T])
}
class ChildClass extends MyClass {
type T = ChildClass
}
Possibly a new language feature has made this easier? Or can I use this.type in some way? It's important to me that I be able to define a helper class that can call into foo in this way.
If you are always returning this, then you can indeed have as return type this.type. Or have you tried it already?
this.type is especially useful e.g. when you want to chain calls to the same object, or provide a static guarantee that you will be returning the same object (and not a copy). For instance, Buffers in Scala have the append operation :+, which returns a Buffer[A], and +=, which returns this.type. The former duplicates the mutable sequence; the latter guarantees that you update the original object.
To follow up on Jean-Phillippe's answer, who wrote his exactly when I'm writing mine, here's the code:
trait SomeTrait {
def foo: this.type = this
}
class UsesTrait extends SomeTrait
object Main {
def main(args: Array[String]) {
println((new UsesTrait).foo) // prints UsesTrait#<hash value>
}
}
I found the following idiom useful:
class MyClass[T] {
self: T =>
def foo(): Option[T] = Some(this)
}
class ChildClass extends MyClass[ChildClass]
new ChildClass().foo()
//--> Option[ChildClass] = Some(ChildClass#2487b1)
I'm trying to implement a Scala trait that handles the details of interfacing with a Java library that requires us to create
What I want to do is something like:
trait SomeTrait[A] extends JavaAPI {
def foo = {
callApi(classOf[A])
}
override def bar = {
foo
}
}
Note that bar is actually overriding a method from a base class, so I can't change it's signature.
I've tried several variations with Manifests, etc., but can't quite get this to work. Is there a way to get the runtime class of a parameterized type?
This flavour should do the trick:
trait SomeTrait[A] {
def foo(implicit ev: Manifest[A]) = {
callApi(ev.erasure)
}
}
update At some point, the manifest must be injected via a method parameter. A constructor would be a good choice, if traits could have them.
Actually, they can! The trait has the constructor of whatever it's mixed-in to, so if you specify an abstract manifest that deriving classes must define...
trait SomeTrait {
def ev: Manifest[_] //abstract
def foo = println(ev.erasure)
}
//this `ev` provides the implementation, note that it MUST be a val, or var
class Concrete[T](implicit val ev: Manifest[T]) extends SomeTrait
And all is good again.
You have to get the manifest in there somehow, and traits have no constructor parameters. Only you can say what tradeoff you want to make. Here's another one.
trait SomeTrait[A] {
implicit def manifesto: Manifest[A]
def foo = println(manifest[A].erasure)
}
object SomeTrait {
def apply[A: Manifest] : SomeTrait[A] = new SomeTrait[A] { def manifesto = manifest[A] }
}
Due to type erasure, the compiler has no way to figure out what the type should be within the trait. Thus what you want can't be done. However, you could make it a class. That way the compiler can pass an evidence parameter when an instance is created.
class SomeTrait[A](implicit ev: Manifest[A]) extends JavaApi {
def foo = {
callApi(ev.erasure)
}
override def bar = {
foo
}
}
It might be a little inconvenient to do so in your code, but you can do this
trait SomeTrait[A] extends JavaAPI {
def objType: Class[A]
def foo = {
callApi(objType)
}
override def bar = {
foo
}
}
object SomeImplementation with SomeTrait[SomeObject] {
val objType: Class[SomeObject] = classOf[SomeObject]
}
I know it is a little wordy, but that's the way I solved this problem. I hope to find a better solution in the future, but this is what I'm using now. Let me know if that helps you.
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.