2011-01-28 2 views
10

Я хочу создать признак, который добавит некоторое свойство в класс и даст возможность цепным методам. Протестировано в Scala 2.8.1.Лучшая практика для реализации признака Scala, который поддерживает цепочку методов

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

Что является наиболее распространенной практикой в ​​подобной ситуации? (Предпочтительным является безопасный тип)

ответ

20

Вы можете явно указать тип экземпляра как тип возвращаемого значения для setProp.

trait SomeProperty { 
    var prop : String = "default" 
    def setProp(s: String):this.type = { 
     prop = s 
     this 
    } 
} 
+0

Это лучше. – lscoughlin

+0

Это работает! Но я не понимаю, почему. Я думаю, 'this.type' равен' SomeProperty', не так ли? Является ли это особенностью Scala? Или также возможно в Java? – ihji

+0

Эта статья полезна. http://scalada.blogspot.com/2008/02/thistype-for-chaining-method-calls.html – ihji

0

Простейшая вещь - использовать общий.

object Value { 

    trait SomeProperty[X] { 
    var str: String = null; 
    def setStr(s: String): X = { 
     str = s; 
     return this.asInstanceOf[X] 
    } 
    } 

    abstract sealed class Value 
    case class IntegerValue(i: Int) 
    case class StringValue(s: String) extends SomeProperty[StringValue] { 
    def foo(): Unit = { 
     println("Foo.") 
    } 
    } 
    case class UnknownValue(o: Any) extends SomeProperty[UnknownValue] { 
    def bar(): Unit = { 
     println("Bar.") 
    } 
    } 

    def main(args: Array[String]): Unit = { 

    new UnknownValue(18).setStr("blah blah blah").bar 
    new StringValue("A").setStr("halb halb halb").foo 
    } 
} 
1

Не уверен, если это то, что вы ищете

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 = [email protected] 

scala> val b = new B 
b: B = [email protected] 

scala> a.setProp("Hi") 
res13: Property[A] with A = [email protected] 

scala> a.setProp("Hi").setProp("Bye") 
res14: Property[A] with A = [email protected] 

scala> b.setProp("D") 
res15: Property[B] with B = [email protected] 
Смежные вопросы