Enquanto o limitante superior de tipos limita um tipo a um subtipo de outro tipo, o limitante inferior de tipos declara um tipo para ser supertipo de outro tipo. O termo T>: A
expressa que o parâmetro de tipo T
ou tipo abstracto T
refere-se a um supertipo do tipo A
.
Aqui está um exemplo onde isso é útil:
case class ListNode[T](h: T, t: ListNode[T]) {
def head: T = h
def tail: ListNode[T] = t
def prepend(elem: T): ListNode[T] =
ListNode(elem, this)
}
O programa acima implementa uma linked list com uma operação de pré-inserção. Infelizmente, esse tipo é invariante no parâmetro de tipo da classe ListNode
; Ou seja, ListNode [String]
não é um subtipo de ListNode [Any]
. Com a ajuda de anotações de variância podemos expressar tal semântica de subtipo:
case class ListNode[+T](h: T, t: ListNode[T]) { ... }
Infelizmente, este programa não compila, porque uma anotação de covariância só é possível se a variável de tipo é usada somente em posições covariantes. Como a variável de tipo T
aparece como um parâmetro de tipo do método prepend
, tal regra é violada. Porém com a ajuda de um limitante inferior de tipo, podemos implementar um método de pré-inserção onde T
só aparece em posições covariantes.
Aqui está o código correspondente:
case class ListNode[+T](h: T, t: ListNode[T]) {
def head: T = h
def tail: ListNode[T] = t
def prepend[U >: T](elem: U): ListNode[U] =
ListNode(elem, this)
}
Nota: o novo método prepend
tem um tipo ligeiramente menos restritivo. Permite, por exemplo, inserir um objeto de um supertipo a uma lista existente. A lista resultante será uma lista deste supertipo.
Aqui está o código que ilustra isso:
object LowerBoundTest extends App {
val empty: ListNode[Null] = ListNode(null, null)
val strList: ListNode[String] = empty.prepend("hello")
.prepend("world")
val anyList: ListNode[Any] = strList.prepend(12345)
}
Contributors to this page:
Contents
- Introdução
- Basics
- Tipos Unificados
- Classes
- Parâmetro com Valor Padrão
- Parâmetros Nomeados
- Traits
- Tuplas
- Composição de Classes Mixin
- Funções de ordem superior
- Funções Aninhadas
- Currying
- Classes Case
- Correspondência de Padrões
- Objetos Singleton
- Padrões de Expressões Regulares
- Objetos Extratores
- For Comprehensions
- Classes Genéricas
- Variâncias
- Limitante Superior de Tipos
- Limitante Inferior de Tipos
- Classes Internas
- Tipos Abstratos
- Tipos Compostos
- Auto Referências Explicitamente Tipadas
- Parâmetros Implícitos
- Conversões Implícitas
- Métodos Polimórficos
- Inferência de Tipo Local
- Operadores
- By-name Parameters
- Anotações
- Packages and Imports
- Package Objects