Почему классы case расширяют только Product, а не Product1, Product2,..., ProductN?
после того, как я узнал, что классы case расширяют Product, я задавался вопросом, почему они не распространяют ProductN. Например, с учетом кода типа:
case class Foo(a: Int)
Я ожидаю, что Foo(1).asInstanceOf[Product1[Int]]
будет работать, но это не так (отмечено с помощью Scala 2.9.1 и подтверждено другими источниками и документацией Product
).
Мне это было интересно, потому что я хотел объявить классы, например:
abstract class UnaryOp[T1 <: Exp[_], R](t1: T1) extends Exp[R] {
this: Product1[T1] =>
}
Таким образом, node для унарной операции должен быть реализован Product1. Было бы неплохо, если бы для этого было просто класс case с одним параметром.
Ответы
Ответ 1
Рассмотрим это:
case class X(n: Int)
case class Y(x: String, y: Int) extends X(y)
Если классы case расширены ProductN
, то это расширит как Product1
, так и Product2
, но параметр типа изменится, поэтому для _1
существуют две разные перегрузки. Это всего лишь одна проблема - я уверен, что есть и другие.
Теперь класс case, наследующий класс case, устарел, и Мартин Одерски теперь рассматривает возможность наследования ProductN. AFAIK, еще не сделано, но препятствие было устранено.
Ответ 2
Я вернул его вскоре после того, как Мартин сказал, что мы можем это сделать. Пока это не работает, но в той степени, в которой это происходит, оно находится за -Xexperimental в строках сборки.
scala> case class Foo[T, U](x1: T, x2: U)
defined class Foo
scala> Foo(List("a"), "b")
res0: Foo[List[java.lang.String],java.lang.String] = Foo(List(a),b)
scala> res0.isInstanceOf[Product2[_,_]]
res1: Boolean = true
Ответ 3
Если бы Product1[Int]
было автоматически расширено, то также необходимо было бы указать val _1: Int
. Хотя я мог себе представить, что он может быть автоматизирован, что a
получает привязку к _1
и т.д. И т.д., Но это не так. Наверное, просто не усложнять ситуацию.