Why cannot this.type be used for new instances

前端 未结 2 1259
灰色年华
灰色年华 2021-01-04 03:40

I\'d like to be able to use this.type to define a method that makes new instances of an immutable case class. Something like this:

trait Expression
{
  def          


        
2条回答
  •  夕颜
    夕颜 (楼主)
    2021-01-04 04:13

    [Note: I am not recommending that you do this.] There's a fair chance you can accomplish what you want. The cast to this.type is a lie, but the JVM doesn't know that and can't throw an exception because the singleton type is a scala concept.

    Now if you're actually using the singleton property of this.type anywhere, this will get you in trouble in a hurry. But if all you want to do is get covariant return types without all the trouble of typing them, with only the small downside of the huge ugly cast all over the place:

    trait Expression
    {
      def left : Expression
      def right : Expression
    
      def new_with_changes(l : Expression, r : Expression) : this.type
    }
    
    case class Derived1(left : Expression, right : Expression) extends Expression {
      def new_with_changes(l : Expression, r : Expression) =
        Derived1(left, right).asInstanceOf[this.type]
    
      def foo() = "Derived1"
    }
    
    case class Derived2(left : Expression, right : Expression) extends Expression {
      def new_with_changes(l : Expression, r : Expression) =
        Derived2(left, right).asInstanceOf[this.type]
    
      def bar() = "Derived2"  
    }
    

    And in action:

    scala> Derived1(Derived1(null,null), null)
    res0: Derived1 = Derived1(Derived1(null,null),null)
    
    scala> res0.new_with_changes(res0, null).bar
    :6: error: value bar is not a member of Derived1
           res0.new_with_changes(res0, null).bar
                                             ^
    
    scala> res0.new_with_changes(res0, null).foo
    res2: java.lang.String = Derived1
    
    scala> Derived2(Derived2(null, null), null)
    res3: Derived2 = Derived2(Derived2(null,null),null)
    
    scala> res3.new_with_changes(null, res3).foo
    :6: error: value foo is not a member of Derived2
           res3.new_with_changes(null, res3).foo
                                             ^
    
    scala> res3.new_with_changes(null, res3).bar
    res6: java.lang.String = Derived2
    

提交回复
热议问题