Me pregunto si hay una razón especial en Java para usar siempre " extends
" en lugar de " implements
" para definir los límites de los parámetros de tipo.
Ejemplo:
public interface C {}
public class A<B implements C>{}
está prohibido pero
public class A<B extends C>{}
es correcto. ¿Cuál es la razón para eso?
java
generics
syntax
design-choices
usuario120623
fuente
fuente
implements
?" - "Porque solo hayextends
".implements
qué no traería nada nuevo y complicaría aún más las cosas. Espero que te sea útil.Respuestas:
No existe una diferencia semántica en el lenguaje de restricción genérico entre si una clase 'implementa' o 'extiende'. Las posibilidades de restricción son 'extendidas' y 'súper', es decir, si esta clase funciona con asignable a la otra (extiende), o es esta clase asignable desde esa (súper).
fuente
class Generic<RenderableT extends Renderable implements Draggable, Droppable, ...> { Generic(RenderableT toDrag) { x = (Draggable)toDrag; } }
uno quisiera verificaciones de tiempo de compilación.La respuesta está aquí :
Así que ahí lo tienes, es un poco confuso, y Oracle lo sabe.
fuente
getFoo(List<? super Foo> fooList)
SOLO funciona con la clase que literalmente se extiende por Foo likeclass Foo extends WildcardClass
. En este caso, aList<WildcardClass>
sería una entrada aceptable. Sin embargo, cualquier clase queFoo
implemente no funcionaríaclass Foo implements NonWorkingWildcardClass
no significaList<NonWorkingWildcardClass>
que será válida engetFoo(List<? super Foo> fooList)
. ¡Claro como el cristal!Probablemente porque para ambos lados (B y C) solo el tipo es relevante, no la implementación. En tu ejemplo
B puede ser una interfaz también. "extend" se utiliza para definir subinterfaces y subclases.
Normalmente pienso en 'Sub extiende Super' como ' Sub es como Super , pero con capacidades adicionales', y 'Clz implementa Intf' como ' Clz es una realización de Intf '. En su ejemplo, esto coincidiría: B es como C , pero con capacidades adicionales. Las capacidades son relevantes aquí, no la realización.
fuente
Puede ser que el tipo base sea un parámetro genérico, por lo que el tipo real puede ser una interfaz de una clase. Considerar:
Además, desde la perspectiva del código del cliente, las interfaces son casi indistinguibles de las clases, mientras que para el subtipo es importante.
fuente
Aquí hay un ejemplo más complicado de dónde se permite extender y posiblemente lo que desea:
public class A<T1 extends Comparable<T1>>
fuente
Es algo arbitrario cuál de los términos usar. Podría haber sido de cualquier manera. Quizás los diseñadores de lenguaje pensaron que "se extiende" como el término más fundamental, e "implementa" como el caso especial para las interfaces.
Pero creo que
implements
tendría un poco más de sentido. Creo que eso comunica más que los tipos de parámetros no tienen que estar en una relación de herencia, pueden estar en cualquier tipo de relación de subtipo.El Glosario de Java expresa una opinión similar .
fuente
Estamos acostumbrados a
y cualquier ligera desviación de estas reglas nos confunde enormemente.
La sintaxis de un tipo enlazado se define como
( JLS 12> 4.4. Variables de tipo>
TypeBound
)Si tuviéramos que cambiarlo, seguramente agregaríamos el
implements
casoy terminan con dos cláusulas procesadas idénticamente
( JLS 12> 4.3. Tipos de referencia y valores>
ClassOrInterfaceType
)excepto que también tendríamos que cuidarnos
implements
, lo que complicaría aún más las cosas.Creo que es la razón principal por la que
extends ClassOrInterfaceType
se usa en lugar deextends ClassType
yimplements InterfaceType
para mantener las cosas simples dentro del complicado concepto. El problema es que no tenemos la palabra correcta para cubrir ambosextends
yimplements
definitivamente no queremos introducir una.<T is ClassTypeA>
<T is InterfaceTypeA>
Aunque
extends
trae algo de desorden cuando va junto con una interfaz, es un término más amplio y puede usarse para describir ambos casos. Intente sintonizar su mente con el concepto de extender un tipo (noextender una clase, noimplementar una interfaz). Usted restringe un parámetro de tipo por otro tipo y no importa cuál sea ese tipo en realidad. Solo importa que sea su límite superior y su supertipo .fuente
De hecho, cuando se usa genérico en la interfaz, la palabra clave también se extiende . Aquí está el ejemplo de código:
Hay 2 clases que implementan la interfaz de saludo:
Y el código de prueba:
fuente