odbhut.shei.chhele
odbhut.shei.chhele

Reputation: 6234

Trying to understand Scala trait

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. 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

Upvotes: 1

Views: 747

Answers (4)

DeepakKg
DeepakKg

Reputation: 349

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

Upvotes: 0

Rashmit Rathod
Rashmit Rathod

Reputation: 773

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 !

Upvotes: 1

Quizzie
Quizzie

Reputation: 879

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()".

Upvotes: 4

Monads are like...
Monads are like...

Reputation: 2053

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.

Upvotes: 2

Related Questions