Estrutura mínima no Scala para coleções com tipo de retorno herdado
Suponha que alguém queira criar uma nova classe genérica,Novel[A]
. Essa classe conterá muitos métodos úteis - talvez seja um tipo de coleção - e, portanto, você deseja subclassificá-la. Mas você deseja que os métodos retornem o tipo da subclasse, não o tipo original. Na Scala 2.8, qual é a quantidade mínima de trabalho necessária para que os métodos dessa classe retornem a subclasse relevante, não a original? Por exemplo,
class Novel[A] /* What goes here? */ {
/* Must you have stuff here? */
def reverse/* What goes here instead of :Novel[A]? */ = //...
def revrev/*?*/ = reverse.reverse
}
class ShortStory[A] extends Novel[A] /* What goes here? */ {
override def reverse: /*?*/ = //...
}
val ss = new ShortStory[String]
val ss2 = ss.revrev // Type had better be ShortStory[String], not Novel[String]
Essa quantidade mínima é alterada se você quiserNovel
ser covariante?
(As coleções 2.8 fazem isso entre outras coisas, mas também brincam com os tipos de retorno de maneiras mais sofisticadas (e úteis) - a questão é quão pouco quadro podemos suportar se quisermos apenas esses subtipos de sempre-retornar-subtipos característica.)
Edit: Suponha que no código acimareverse
faz uma cópia. Se alguém fizer uma modificação no local e depois retornar a si mesmo, poderá usarthis.type
, mas isso não funciona porque a cópia não estáthis
.
Arjan vinculou-se a outra pergunta que sugere a seguinte solução:
def reverse: this.type = {
/*creation of new object*/.asInstanceOf[this.type]
}
que basicamente reside no sistema de tipos para obter o que queremos. Mas isso não é realmente uma solução, porque agora que mentimos para o sistema de tipos, o compilador não pode nos ajudar a garantir que realmenteFaz arranje umShortStory
de volta quando pensamos que fazemos. (Por exemplo, não precisaríamos substituirreverse
no exemplo acima para deixar o compilador feliz, mas nossos tipos não seriam o que queríamos.)