Scala: implementing method with return type of concrete instance

前端 未结 4 570
北恋
北恋 2021-01-30 07:23

I need a way to enforce a method in an abstract class to have a return type of the concrete class of the object it is called on. The most common example is a copy

4条回答
  •  没有蜡笔的小新
    2021-01-30 07:52

    The only solution I could think of was this one:

    trait CanCopy[T <: CanCopy[T]] { self: T =>
      type Self >: self.type <: T
      def copy(newId: Int): Self
    }
    
    abstract class A(id: Int) { self:CanCopy[_] =>
      def copy(newId: Int): Self
    }
    

    The following would compile:

    class B(id: Int, x: String) extends A(id) with CanCopy[B] {
      type Self = B
      def copy(newId: Int) = new B(newId, x)
    }
    
    class C(id: Int, y: String, z: String) extends A(id) with CanCopy[C] {
      type Self = C
      def copy(newId: Int) = new C(newId, y, z)
    }
    

    The following would not compile:

    class D(id: Int, w: String) extends A(id) with CanCopy[D] {
      type Self = A
      def copy(newId: Int) = new D(newId, w) // returns an A
    }
    
    class E(id: Int, v: String) extends A(id) with CanCopy[E] {
      type Self = B
      def copy(newId: Int) = new B(newId, "")
    }
    

    Edit

    I actually forgot to remove the copy method. This might be a bit more generic:

    trait StrictSelf[T <: StrictSelf[T]] { self: T =>
      type Self >: self.type <: T
    }
    
    abstract class A(id: Int) { self:StrictSelf[_] =>
      def copy(newId:Int):Self
    }
    

提交回复
热议问题