Hoje, eu li alguns artigos sobre Covariância, Contravariância (e Invariância) em Java. Eu li o artigo da Wikipedia em inglês e alemão e algumas outras postagens de blog e artigos da IBM.
Mas ainda estou um pouco confuso sobre o que exatamente se trata? Alguns dizem que é sobre relacionamento entre tipos e subtipos, alguns dizem que é sobre conversão de tipo e alguns dizem que é usado para decidir se um método é sobrescrito ou sobrecarregado.
Portanto, estou procurando uma explicação fácil em inglês simples, que mostre a um iniciante o que é Covariância e Contravariância (e Invariância). Ponto positivo para um exemplo fácil.
Respostas:
Tudo acima.
No fundo, esses termos descrevem como a relação de subtipo é afetada pelas transformações de tipo. Ou seja, se
A
eB
são tipos,f
é uma transformação de tipo, e ≤ a relação de subtipo (ou seja,A ≤ B
significa queA
é um subtipo deB
), temosf
é covariante seA ≤ B
implica quef(A) ≤ f(B)
f
é contravariante seA ≤ B
implica quef(B) ≤ f(A)
f
é invariante se nenhuma das opções acima for válidaVamos considerar um exemplo. Deixe
f(A) = List<A>
ondeList
é declarado porÉ
f
covariante, contravariante ou invariante? Covariante significaria que aList<String>
é um subtipo deList<Object>
, contravariante que aList<Object>
é um subtipo deList<String>
e invariante que nenhum é um subtipo do outro, ou seja,List<String>
eList<Object>
são tipos inconversíveis. Em Java, o último é verdade, dizemos (um tanto informalmente) que os genéricos são invariantes.Outro exemplo. Deixe
f(A) = A[]
. Éf
covariante, contravariante ou invariante? Ou seja, String [] é um subtipo de Object [], Object [] um subtipo de String [], ou nenhum é um subtipo do outro? (Resposta: Em Java, os arrays são covariantes)Isso ainda era bastante abstrato. Para tornar isso mais concreto, vamos examinar quais operações em Java são definidas em termos da relação de subtipo. O exemplo mais simples é a atribuição. A declaração
irá compilar apenas se
typeof(y) ≤ typeof(x)
. Ou seja, acabamos de saber que as declaraçõesnão vai compilar em Java, mas
vai.
Outro exemplo onde a relação de subtipo é importante é uma expressão de invocação de método:
Falando informalmente, essa instrução é avaliada atribuindo o valor de
a
ao primeiro parâmetro do método, executando o corpo do método e atribuindo o valor de retorno do método aresult
. Como a atribuição simples no último exemplo, o "lado direito" deve ser um subtipo do "lado esquerdo", ou seja, esta instrução só pode ser válida setypeof(a) ≤ typeof(parameter(method))
ereturntype(method) ≤ typeof(result)
. Ou seja, se o método for declarado por:nenhuma das seguintes expressões irá compilar:
mas
vai.
Outro exemplo em que a subtipagem é importante é a substituição. Considerar:
Onde
Informalmente, o tempo de execução irá reescrever isso para:
Para a linha marcada para compilar, o parâmetro do método do método sobrescrito deve ser um supertipo do parâmetro do método do método sobrescrito, e o tipo de retorno um subtipo do método sobrescrito. Falando formalmente,
f(A) = parametertype(method asdeclaredin(A))
deve ser pelo menos contravariante, e sef(A) = returntype(method asdeclaredin(A))
deve ser pelo menos covariante.Observe o "pelo menos" acima. Esses são requisitos mínimos que qualquer linguagem de programação orientada a objetos segura de tipo estaticamente razoável irá impor, mas uma linguagem de programação pode optar por ser mais estrita. No caso do Java 1.4, os tipos de parâmetro e tipos de retorno de método devem ser idênticos (exceto para eliminação de tipo) ao substituir métodos, ou seja,
parametertype(method asdeclaredin(A)) = parametertype(method asdeclaredin(B))
ao substituir. Desde Java 1.5, os tipos de retorno covariant são permitidos durante a substituição, ou seja, o seguinte será compilado em Java 1.5, mas não em Java 1.4:Espero ter coberto tudo - ou melhor, arranhado a superfície. Ainda assim, espero que ajude a entender o conceito abstrato, mas importante, de variância de tipo.
fonte
A ≤ B
. Essa notação torna as coisas muito mais simples e significativas. Boa leitura ...Pegando o sistema de tipo java e depois as classes:
Qualquer objeto de algum tipo T pode ser substituído por um objeto do subtipo de T.
VARIÂNCIA DE TIPO - OS MÉTODOS DE CLASSE TÊM AS SEGUINTES CONSEQUÊNCIAS
Pode ser visto que:
Agora co- e contra- relacionam-se com B sendo o subtipo de A. As seguintes tipificações mais fortes podem ser introduzidas com um conhecimento mais específico. No subtipo.
Covariância (disponível em Java) é útil, para dizer que se retorna um resultado mais específico no subtipo; especialmente visto quando A = T e B = S. A contravariância diz que você está preparado para lidar com um argumento mais geral.
fonte
A variância diz respeito às relações entre classes com diferentes parâmetros genéricos. Seus relacionamentos são a razão pela qual podemos lançá-los.
Variância Co e Contra são coisas bastante lógicas. O sistema de tipo de linguagem nos força a apoiar a lógica da vida real. É fácil entender por exemplo.
Covariância
Por exemplo, você quer comprar uma flor e tem duas floriculturas em sua cidade: uma loja de rosas e uma loja de margaridas.
Se você perguntar a alguém "onde fica a loja de flores?" e alguém lhe disser onde fica a rose shop, tudo bem? sim, porque rosa é uma flor, se quiseres comprar uma flor podes comprar uma rosa. O mesmo se aplica se alguém lhe responder com o endereço da loja de margaridas. Este é um exemplo de covariância : você pode lançar
A<C>
paraA<B>
, ondeC
é uma subclasse deB
, seA
produz valores genéricos (retorna como resultado da função). A covariância tem a ver com produtores.Tipos:
A pergunta é "onde fica a floricultura?", A resposta é "loja de flores lá":
Contravariância
Por exemplo, você deseja presentear sua namorada com flores. Se sua namorada adora qualquer flor, você pode considerá-la uma pessoa que adora rosas ou uma pessoa que adora margaridas? sim, porque se ela ama qualquer flor ela amaria rosa e margarida. Este é um exemplo de contravariância : você tem permissão para lançar
A<B>
paraA<C>
, ondeC
é subclasse deB
, seA
consome valor genérico. A contravariância diz respeito aos consumidores.Tipos:
Você está considerando sua namorada que ama qualquer flor como alguém que ama rosas, e está dando a ela uma rosa:
Você pode encontrar mais na Fonte .
fonte