Java equivalente ai metodi di estensione C #

Sto cercando di implementare una funzionalità in un elenco di oggetti come farei in C # utilizzando un metodo di estensione.

Qualcosa come questo:

List list; // ... List initialization. list.getData(id); 

Come posso farlo in Java?

Java non supporta i metodi di estensione.

Invece, puoi creare un metodo statico normale o scrivere la tua class.

I metodi di estensione non sono solo il metodo statico e non solo lo zucchero syntax di comodità, in realtà sono uno strumento abbastanza potente. La cosa principale è la possibilità di sovrascrivere diversi metodi basati sull’istanza di parametri di diversi generici. Questo è simile alle classi di tipi di Haskell e, in effetti, sembra che siano in C # per supportare le Monade di C # (cioè LINQ). Anche lasciando cadere la syntax LINQ, non conosco ancora alcun modo per implementare interfacce simili in Java.

E non penso sia ansible implementarli in Java, a causa della semantica di cancellazione di tipo Java dei parametri generici.

Project Lombok fornisce un’annotazione @ExtensionMethod che può essere utilizzata per ottenere la funzionalità richiesta.

Il linguaggio XTend – che è un super-set di Java, e compila il codice sorgente Java 1 – supporta questo.

Java non ha questa caratteristica. Puoi invece creare una sottoclass regolare dell’implementazione della lista o creare una class interna anonima:

 List list = new ArrayList() { public String getData() { return ""; // add your implementation here. } }; 

Il problema è chiamare questo metodo. Puoi farlo “sul posto”:

 new ArrayList() { public String getData() { return ""; // add your implementation here. } }.getData(); 

Un’altra opzione è quella di utilizzare le classi ForwardingXXX dalla libreria google-guava.

Sembra che ci siano alcune piccole possibilità che i metodi Defender (cioè i metodi predefiniti) possano farcela in Java 8. Tuttavia, per quanto li comprendo, consentono solo all’autore di interface di estenderlo retrotriggersmente, non a utenti arbitrari.

Defender Methods + Interface Injection sarebbe quindi in grado di implementare completamente i metodi di estensione in stile C #, ma AFAICS, Interface Injection non è ancora presente sulla roadmap di Java 8.

Manifold fornisce Java con i metodi di estensione stile C # e molte altre funzionalità. Diversamente da altri strumenti, Manifold non ha limitazioni e non soffre di problemi con generici, lambda, IDE, ecc. Manifold offre molte altre funzionalità come i tipi personalizzati in stile F #, interfacce strutturali in stile TypeScript e tipi di expando in stile Javascript .

Inoltre, IntelliJ fornisce supporto completo per Manifold tramite il plug-in Manifold.

Manifold è un progetto open source disponibile su github .

Un po ‘tardi alla festa su questa domanda, ma nel caso qualcuno lo trovasse utile ho appena creato una sottoclass:

 public class ArrayList2 extends ArrayList { private static final long serialVersionUID = 1L; public T getLast() { if (this.isEmpty()) { return null; } else { return this.get(this.size() - 1); } } } 

Si potrebbe usare il modello di progettazione orientato agli oggetti del decoratore . Un esempio di questo modello utilizzato nella libreria standard di Java sarebbe DataOutputStream .

Ecco un codice per aumentare la funzionalità di un elenco:

 public class ListDecorator implements List { public final List wrapee; public ListDecorator(List wrapee) { this.wrapee = wrapee; } // implementation of all the list's methods here... public  ListDecorator map(Transform transformsr) { ArrayList result = new ArrayList(size()); for (E element : this) { R transformsd = transformsr.transform(element); result.add(transformsd); } return new ListDecorator(result); } } 

PS Sono un grande fan di Kotlin . Ha metodi di estensione e gira anche su JVM.

Tecnicamente l’estensione C # non ha equivalenti in Java. Ma se si desidera implementare tali funzioni per un codice più pulito e per la manutenibilità, è necessario utilizzare il framework Manifold.

 package extensions.java.lang.String; import manifold.ext.api.*; @Extension public class MyStringExtension { public static void print(@This String thiz) { System.out.println(thiz); } @Extension public static String lineSeparator() { return System.lineSeparator(); } } 

Java 8 ora supporta i metodi predefiniti , che sono simili ai metodi di estensione di C# .