Заморозить мозг по следующим вопросам:

abstract class A {
  def withName(name: String): this.type
}

case class B(name: String) extends A {
  def withName(name: String): this.type = copy(name = name.reverse)
}

case class C(name: String) extends A {
  def withName(name: String): this.type = copy(name = name.toLowerCase)
}

В основном я хочу, чтобы методы в B и C возвращали тот же тип, что и они сами.

0
sksamuel 2 Апр 2014 в 13:04
Если подклассы A не являются изменчивыми и фактически мутируют и возвращаются внутри withName, ваша подпись не имеет смысла. По своей сигнатуре (тип возврата this.type) withName может возвращать только себя, но withName при этом должен менять имя. Своего рода уловка-22.
 – 
Régis Jean-Gilles
2 Апр 2014 в 16:32
Да, я знаю, что это не имеет смысла, потому что я говорю, верни меня, но копия всегда вернет мою копию, но это то, о чем я прошу. Я хочу, чтобы B возвращал тип B, а C возвращал тип C.
 – 
sksamuel
2 Апр 2014 в 17:04
Gzm0 правильно резюмировал то, что я пытался сделать. Спасибо за все ответы.
 – 
sksamuel
2 Апр 2014 в 17:09

2 ответа

Лучший ответ

Конечно, вы также можете использовать члены типа для того же:

abstract class A {
  type R <: A
  def withName(name: String): R
}

case class B(name: String) extends A {
  type R = B
  def withName(name: String): R = copy(name = name.reverse)
}
4
gzm0 2 Апр 2014 в 16:15
Теперь готовим на газе!
 – 
sksamuel
2 Апр 2014 в 17:08
На самом деле это "...с газом".
 – 
Randall Schulz
2 Апр 2014 в 21:40

Два возможных решения:

В ролях:

abstract class A {
  def withName(name: String): this.type
}

case class B(name: String) extends A {
  def withName(name: String): this.type = copy(name = name.reverse).asInstanceOf[this.type]
}

case class C(name: String) extends A {
  def withName(name: String): this.type = copy(name = name.toLowerCase).asInstanceOf[this.type]
}

F-ограниченный полиморфизм:

abstract class A[T <: A[_]] {
  def withName(name: String): T
}

case class B(name: String) extends A[B] {
  def withName(name: String): B = copy(name = name.reverse)
}

case class C(name: String) extends A[C] {
  def withName(name: String): C = copy(name = name.toLowerCase)
}
1
Yuriy 2 Апр 2014 в 15:43
Я знал оба этих метода. Я надеялся, что есть хороший способ сделать это, зависящий от пути. Я проголосую за вас, потому что вы отвечаете на мой вопрос «есть ли лучший способ сделать это», говоря «нет» :)
 – 
sksamuel
2 Апр 2014 в 16:12
2
Версия с приведением - это действительно подрыв системы типов (или, другими словами, вы "врёте"). this.type означает «тип этого единственного экземпляра», поэтому единственно правильное решение — вернуть this. Но здесь вы возвращаете другой экземпляр, а затем разыгрываете его, эффективно притворяясь, что это то же самое insatance, когда это не так.
 – 
Régis Jean-Gilles
2 Апр 2014 в 16:28