Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Best practice to implement Scala trait which supports method chaining

I want to make a trait which add some property to a class and make it possible to chain methods. Tested in Scala 2.8.1.

trait SomeProperty {
    var prop : String = "default"
    def setProp(s: String) = {
        prop = s
        this
    }
}
sealed abstract class Value
case class IntegerValue(v: Int) extends Value
case class FloatValue(v: Float) extends Value with SomeProperty {
    def foo() = { println("I'm foo.") }
}
case object UnknownValue extends Value with SomeProperty {
    def bar() = { println("I'm bar.") }
}

scala> val x = UnknownValue
scala> x.setProp("test").bar()
<console>:10: error: value bar is not a member of SomeProperty
   x.setProp("test").bar()

What is the most common practice in this kind of situation? (Type-safe way is preferred)

like image 758
ihji Avatar asked Jan 28 '11 08:01

ihji


People also ask

Can scala traits have methods?

In scala, trait is a collection of abstract and non-abstract methods. You can create trait that can have all abstract methods or some abstract and some non-abstract methods. A variable that is declared either by using val or var keyword in a trait get internally implemented in the class that implements the trait.

How do you implement a trait in scala?

In Scala, we are allowed to implement the method(only abstract methods) in traits. If a trait contains method implementation, then the class which extends this trait need not implement the method which already implemented in a trait. As shown in the below example. Traits does not contain constructor parameters.

When can you use traits in scala?

When to Use Traits? If the behavior will not be reused, then make it a concrete class. It is not reusable behavior after all. If it might be reused in multiple, unrelated classes, make it a trait.

Can a scala trait take parameters?

Unlike a class, Scala traits cannot be instantiated and have no arguments or parameters. However, you can inherit (extend) them using classes and objects.


Video Answer


2 Answers

You can explicitly specify the instance type as the return type for setProp.

trait SomeProperty {
    var prop : String = "default"
    def setProp(s: String):this.type = {
        prop = s
        this
    }
}
like image 97
Monkey Avatar answered Oct 06 '22 18:10

Monkey


Not sure if this is what you're looking for

scala> trait Property[T] {
     |   me: T =>
     |   var prop:String=""
     |   def setProp(s:String) = {
     |     prop=s
     |     me
     |   }
     | }
defined trait Property

scala> class A extends Property[A]
defined class A

scala> class B extends Property[B]
defined class B

scala> val a= new A
a: A = A@694a18

scala> val b = new B
b: B = B@1108691

scala> a.setProp("Hi")
res13: Property[A] with A = A@694a18

scala> a.setProp("Hi").setProp("Bye")
res14: Property[A] with A = A@694a18

scala> b.setProp("D")
res15: Property[B] with B = B@1108691
like image 44
Jim Avatar answered Oct 06 '22 18:10

Jim