Więc jest to dość bezpośredni port this Java question do ScalaUnikanie zbędnych parametry rodzajowe w Scala
Mamy kilka cech, które mają parametry rodzajowe w następujący sposób:
trait Ident { }
trait Container[I <: Ident] {
def foo(id: I): String
}
trait Entity[C <: Container[I], I <: Ident] {
def container: C
def foo(id: I) = container.foo(id)
}
To działa, ale jest to mało niezdarny, ponieważ musimy podać typ Tożsamości i typ Pojemnika podczas definiowania podklasy Podmiotu. Podczas gdy w rzeczywistości tylko rodzaj Container wystarczy informacja o typie sama:
class MyIdent extends Ident { }
class MyContainer extends Container[MyIdent] { }
class MyEntity extends Entity[MyContainer,MyIdent] { }
// ^^^^^^^ shouldn't really be necessary
Korzystanie typ egzystencjalne eliminuje potrzebę podjęcia Entity dwa parametry ... ale oczywiście nie można odwoływać się do niego później.
trait Entity[C <: Container[I] forSome { type I <: Ident }] {
def container: C
def foo(id: I) = container.foo(id)
// ^^^ complains it has no idea what 'I' is here
}
Podobnie przekształcania rzeczy do używania typów członkowskie również nie działa ...
trait Ident { }
trait Container {
type I <: Ident
def foo(id: I): String
}
trait Entity {
type C <: Container
def container: C
def foo(id: C#I) = container.foo(id)
// ^^ type mismatch
}
Więc czy ktoś wie, czy jest eleganckie rozwiązanie tego problemu w Scala?
Nie sądzę, że odpowiedź będzie znacznie inna niż wersja Java. Tak naprawdę nie ma sposobu na pominięcie parametru type bez utraty informacji o typie, które by się z nim wiązały. –
Czy jest to opcja, aby zrobić 'container' a' val'? – sepp2k
@MichaelZajac Tak więc w definicji "MyEntity" drugi parametr podany do Entity jest zbędny: po prostu nie ma innego możliwego typu, jakiego można użyć tam, poza "MyIdent", dosłownie wszystko inne da błędy kompilacji. Oczywiście, czy można uniknąć tej redundancji w Scali, to kolejne pytanie :-) –