Java 8 agregar extensión / método predeterminado a la clase


Estoy buscando un java equivalente a la característica de métodos de extensión C#. Ahora he estado leyendo sobre los métodos predeterminados de Java 8, pero por lo que puedo ver, solo puedo agregar estos a las interfaces...

Is ¿hay alguna característica de lenguaje que me permita escribir un método de extensión para una clase final que no implemente una interfaz? (Prefiero no tener que envolverlo...)

Author: Cheetah, 2014-06-07

4 answers

Los métodos de extensión C# son solo azúcar sintáctica para métodos estáticos que toman el tipo extendido como primer argumento. Los métodos predeterminados de Java son algo completamente diferente. Para imitar los métodos de extensión de C#, simplemente escriba los métodos estáticos habituales. Sin embargo, no tendrá el azúcar sintático; Java no tiene esta característica.

Los métodos predeterminados de Java son métodos virtuales reales. Por ejemplo, pueden ser anulados. Considere una clase X heredada de una interfaz I que declara un método predeterminado foo(). Si X o cualquiera de sus superclases declara ningún método propio foo(), entonces X obtendrá la implementación foo() de I. Ahora, una subclase Y de X puede anular X.foo() como un método habitual. Por lo tanto, los métodos predeterminados no son solo azúcar sintáctico. Son extensiones reales del mecanismo de anulación y herencia del método que no pueden ser imitadas por otras características del lenguaje.

Los métodos predeterminados incluso requieren soporte especial de VM, por lo que ni siquiera son solo un compilador característica: Durante la carga de la clase, la jerarquía de una clase tiene que ser comprobada para determinar qué métodos predeterminados heredará. Por lo tanto, esta decisión se toma en tiempo de ejecución, no en tiempo de compilación. Lo bueno de esto es que no tiene que recompilar una clase cuando una interfaz que hereda obtiene un nuevo método predeterminado: La VM, en el tiempo de carga de la clase, le asignará ese nuevo método.

 21
Author: gexicide,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-04-12 21:45:33

Los métodos de extensión de C# son static y use-site, mientras que los métodos predeterminados de Java son virtual y declaration-site.

Lo que creo que está esperando es la capacidad de "monkey-patch" un método en una clase que no controla, pero Java no le da eso (por diseño; fue considerado y rechazado.)

Otro beneficio de los métodos predeterminados sobre el enfoque de C # es que son reflectivamente detectables, y de hecho de la fuera, no se vea diferente de los métodos de interfaz "regulares".

Una ventaja de los métodos de extensión de C#sobre los métodos predeterminados de Java es que con los genéricos reificados de C#, los métodos de extensión se inyectan en tipos, no en clases, por lo que puede inyectar un método sum() en List<int>.

Sobre todo, la principal diferencia filosófica entre los métodos predeterminados de Java y los métodos de extensión de C#es que C# le permite inyectar métodos en tipos que no controla (que seguramente es conveniente para los desarrolladores), mientras que los métodos de extensión de Java son una parte de primera clase de la API en la que aparecen (se declaran en la interfaz, son reflectivamente detectables, etc.) Esto refleja varios principios de diseño; los desarrolladores de bibliotecas deben ser capaces de mantener el control de sus API, y el uso de la biblioteca debe ser transparente calling llamar al método x() en el tipo Y debe significar lo mismo en todas partes.

 18
Author: Brian Goetz,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-04-13 13:30:25

Java no tiene métodos de extensión. Los métodos predeterminados no son métodos de extensión. Echemos un vistazo a cada característica.

Métodos predeterminados de Java

Problemas resueltos:

  1. Muchos objetos pueden implementar la misma interfaz y todos ellos pueden usar la misma implementación para un método. Una clase base podría resolver este problema, pero solo si los implementadores de la interfaz no tienen una clase base ya que Java no admite herencia múltiple.
  2. A una API le gustaría agregar un método a una interfaz sin romper los consumidores API. Agregar un método con una implementación predeterminada resuelve esto.

Los métodos predeterminados de Java son una característica para agregar una implementación predeterminada a una interfaz. Así que los objetos que extienden una interfaz no tienen que implementar el método, solo podrían usar el método predeterminado.

interface IA { default public int AddOne(int i) { return i + 1; } }

Cualquier objeto que implemente IA no tiene que implementar AddOne porque hay un método predeterminado que se usaría.

public class MyClass implements IA { /* No AddOne implementation needed */ } 

Falta C# esta característica y se mejorará en gran medida mediante la adición de esta característica. (Actualización: Característica que viene en C # 8)

Método de extensión de C#

Problemas resueltos:

  1. Capacidad para agregar métodos a clases selladas.
  2. Capacidad para agregar métodos a clases desde bibliotecas de terceros sin forzar la herencia.
  3. Capacidad para agregar métodos a las clases de modelo en entornos donde los métodos de las clases de modelo no están permitidos por razones convencionales.
  4. La capacidad para intellisense para presentarle estos métodos.

Ejemplo: El tipo string es una clase sellada en C#. No puede heredar de la cadena ya que está sellada. Pero puede agregar métodos que puede llamar desde una cadena.

var a = "mystring";
a.MyExtensionMethed()

Java carece de esta característica y se mejoraría enormemente al agregar esta característica.

Conclusión

No hay nada similar en los métodos predeterminados de Java y las características de los métodos de extensión de C#. Son completamente diferentes y resuelven completamente diferentes problema.

 17
Author: Rhyous,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-05-18 13:46:33

Es posible tener métodos de extensión con algunos trucos.

Puedes probar Lombok o XTend. Aunque los métodos de extensión no vienen con la implementación de Java lista para usar, tanto Lombok como XTend ofrecen una solución completamente funcional.

Lombok es un marco de procesamiento de código independiente simple, que hace que la mayoría de los problemas específicos de Java criticados sean menos dolorosos, incluida la extensión método: https://projectlombok.org/features/experimental/ExtensionMethod.html

Xtend http://www.eclipse.org/xtend / va unos años luz hacia adelante, e implementa un lenguaje que es una combinación de las mejores partes de lenguajes modernos como Scala en la parte superior de Java y Java type system. Esto permite implementar algunas clases en Xtend y otras en Java dentro del mismo proyecto. El código Xtend cumple con el código Java válido, por lo que no hay magia JVM debajo del capó. En el por otro lado, es un poco demasiado si solo faltan métodos de extensión.

JPropel https://github.com/nicholas22/jpropel-light implementa métodos de extensión de estilo LINQ en Java usando Lombok. Vale la pena echar un vistazo:)

 6
Author: Gee Bee,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-04-11 23:54:04