В некоторых случаях я хотел бы использовать внутренний тип в качестве альтернативы универсального типа, например, в следующем случае вместо определения Dependent[T <: BaseType]
я определяю его следующим образом:
abstract class BaseType {
type N
def create(v: Int): N
class Dependent(val n: N) {
def +(other: Dependent) = new Dependent(create(n.hashCode() + n.hashCode()))
}
}
object BaseType {
class Aggregator[T <: BaseType](val seq: Seq[T#Dependent]) {
def result() = seq.reduce(_ + _)
}
}
Очевидно, этоне будет компилироваться, потому что Dependent
теперь является классом Inner, а разные Dependent
, созданные в разных экземплярах BaseType, не могут взаимодействовать друг с другом.(Кстати, будет сгенерирована следующая ошибка компиляции)
Error:(15, 35) type mismatch;
found : T#Inner
required: _33.Inner where val _33: T
def result() = seq.reduce(_ + _)
Однако эта проблема должна иметь тривиальное решение в Scala, потому что в Java такая задача может быть легко решена с помощью:
static class Dependent { ...
Нет смысла иметь более длинный код в Scala, чем Java.Непосредственной аналогией в scala будет добавление принудительного правила в BaseType, которое требует, чтобы все его реализации были объектами / синглтонами, а не классами.Однако я не видел такой возможности.
Итак, вопрос в том, КАКОЙ КРАТКИЙ способ сделать то же самое, что легко сделать в Java?
ОБНОВЛЕНИЕ очевидно, я не совсем понимал свое намерение. Я хочу не использовать класс Dependent
как есть, а расширять BaseType таким образом, чтобы BaseType
служил параметром типа для Dependent
, например, если я определяю 2 объекта:
object Sub1 extends BaseType {
override type N = Long
override def create(v: Int): N = v.toLong
}
object Sub2 extends BaseType {
override type N = Double
override def create(v: Int): N = v.toDouble
}
Тогда оба знака +
и Aggregator
могут использоваться на 2 зависимых, только если они принадлежат одному и тому же объекту, что означает, что это удастся:
assert(
new Aggregator(
Seq(
new Sub1.Dependent(1),
new Sub1.Dependent(2)
)).result() == new Sub1.Dependent(1) +
new Sub1.Dependent(2)
)
но это не удастся:
assert(
new Aggregator(
Seq(
new Sub1.Dependent(1),
new Sub2.Dependent(2)
)).result() == new Sub1.Dependent(1) +
new Sub2.Dependent(2)
)
, потому что 2 зависимых экземпляра имеют разные типы, однако с последним компилятором scala даже первый выйдет из строя, потому что к моменту определения Агрегатора он не знает T <: BaseType
является синглтоном.