Scala конструкторы классов и абстрактные типы
Я хочу использовать абстрактный тип, а не параметр типа.
В моем конструкторе generic classes я хочу иметь параметр типа generic, но код не компилируется:
class SomeOtherClass(val s: S){
type S
}
Ошибка компилятора scala "не найдена: type S"
Если я использую параметр типа вместо абстрактного типа, то он работает:
class SomeClass[T](val t: T){
//...
}
Заставляет ли scala использовать параметр типа, а не абстрактный тип, если я хочу иметь общий параметр в конструкторе?
Есть ли другой способ сделать это?
Ответы
Ответ 1
В этом случае вы в значительной степени вынуждены использовать параметры типового типа. Вы можете обойти это, объявив тип вне класса, но тогда вам нужно создать экземпляр обертки, а затем объект, и он будет довольно уродливым довольно быстро.
trait FooDef {
type T
class Foo(val x: T)
}
val ifd = new FooDef { type T = Int }
val ifoo = new ifd.Foo(5)
val sfd = new FooDef { type T = String }
val sfoo = new sfd.Foo("hi")
def intFoos(f: fd.Foo forSome { val fd: FooDef {type T = Int} }) = f.x + 1
Ответ 2
Если абстрактный тип не указан, ваш класс должен быть абстрактным. Таким образом, вам не нужен параметр вообще. Эквивалентом с абстрактным типом будет:
abstract class SomeOtherClass {
type S
val s: S
}
Затем на сайте использования:
val x = new SomeOtherClass {
type S = String
val s = "abc"
}
Без параметра абстрактный класс здесь эквивалентен признаку. Вам лучше использовать черту, потому что она менее ограничительна (вы можете расширить только один базовый класс).
Ответ 3
Как компилятор должен знать, какой тип он должен использовать там? Либо вы должны указать тип напрямую, что не имеет смысла, либо использовать общий. Есть один способ заставить его работать, но я не думаю, что он вам поможет.
class SomeClass(s: SomeClass#S) {
type S
}
Но поскольку SomeClass # S не определен, его экземпляр отсутствует.
Ответ 4
Может быть, вы хотите что-то вроде этого? Таким образом, вы можете иметь несколько экземпляров AbstractFooFactory
, каждый из которых производит Foo
с другим значением для s.
trait AbstractFooFactory {
type S
def makeFoo(s:S):Foo
class Foo(val s:S) {}
}
object StringFooFactory extends AbstractFooFactory {
override type S = String
override def makeFoo(s:String) = new Foo(s)
}
val b = StringFooFactory.makeFoo("bar")
val s:String = b.s