son sobrecarga que programacion parĂ¡metros parametros metodos los funciones ejemplos crear con argumentos java lambda functional-programming java-8 functional-interface

sobrecarga - Proveedor Java 8 con argumentos en el constructor



que son los parĂ¡metros o argumentos en java (6)

¿Por qué los proveedores solo admiten constructores sin argumentos?

Si el constructor predeterminado está presente, puedo hacer esto:

create(Foo::new)

Pero si el único constructor toma una cadena, tengo que hacer esto:

create(() -> new Foo("hello"))


¿Por qué los proveedores solo trabajan con constructores sin argumentos?

Debido a que un constructor de 1 argumento es isomorfo a una interfaz SAM con 1 argumento y 1 valor de retorno, como java.util.function.Function<T,R> R apply(T) .

Por otro lado, el T get() Supplier<T> es isomorfo a un constructor de cero argumentos.

Simplemente no son compatibles. O bien, su método create() debe ser polimórfico para aceptar varias interfaces funcionales y actuar de manera diferente dependiendo de los argumentos que se proporcionen o debe escribir un cuerpo lambda para que actúe como código de unión entre las dos firmas.

¿Cuál es su expectativa insatisfecha aquí? ¿Qué debería suceder en tu opinión?


Empareje el proveedor con una interfaz funcional.

Aquí hay un código de muestra que preparé para demostrar "vincular" una referencia de constructor a un constructor específico con Function y también diferentes formas de definir e invocar las referencias de constructor de "fábrica".

import java.io.Serializable; import java.util.Date; import org.junit.Test; public class FunctionalInterfaceConstructor { @Test public void testVarFactory() throws Exception { DateVar dateVar = makeVar("D", "Date", DateVar::new); dateVar.setValue(new Date()); System.out.println(dateVar); DateVar dateTypedVar = makeTypedVar("D", "Date", new Date(), DateVar::new); System.out.println(dateTypedVar); TypedVarFactory<Date, DateVar> dateTypedFactory = DateVar::new; System.out.println(dateTypedFactory.apply("D", "Date", new Date())); BooleanVar booleanVar = makeVar("B", "Boolean", BooleanVar::new); booleanVar.setValue(true); System.out.println(booleanVar); BooleanVar booleanTypedVar = makeTypedVar("B", "Boolean", true, BooleanVar::new); System.out.println(booleanTypedVar); TypedVarFactory<Boolean, BooleanVar> booleanTypedFactory = BooleanVar::new; System.out.println(booleanTypedFactory.apply("B", "Boolean", true)); } private <V extends Var<T>, T extends Serializable> V makeVar(final String name, final String displayName, final VarFactory<V> varFactory) { V var = varFactory.apply(name, displayName); return var; } private <V extends Var<T>, T extends Serializable> V makeTypedVar(final String name, final String displayName, final T value, final TypedVarFactory<T, V> varFactory) { V var = varFactory.apply(name, displayName, value); return var; } @FunctionalInterface static interface VarFactory<R> { // Don''t need type variables for name and displayName because they are always String R apply(String name, String displayName); } @FunctionalInterface static interface TypedVarFactory<T extends Serializable, R extends Var<T>> { R apply(String name, String displayName, T value); } static class Var<T extends Serializable> { private String name; private String displayName; private T value; public Var(final String name, final String displayName) { this.name = name; this.displayName = displayName; } public Var(final String name, final String displayName, final T value) { this(name, displayName); this.value = value; } public void setValue(final T value) { this.value = value; } @Override public String toString() { return String.format("%s[name=%s, displayName=%s, value=%s]", getClass().getSimpleName(), this.name, this.displayName, this.value); } } static class DateVar extends Var<Date> { public DateVar(final String name, final String displayName) { super(name, displayName); } public DateVar(final String name, final String displayName, final Date value) { super(name, displayName, value); } } static class BooleanVar extends Var<Boolean> { public BooleanVar(final String name, final String displayName) { super(name, displayName); } public BooleanVar(final String name, final String displayName, final Boolean value) { super(name, displayName, value); } } }


Eso es solo una limitación de la sintaxis de referencia del método: que no puede pasar ninguno de los argumentos. Así es como funciona la sintaxis.


La interfaz Supplier<T> representa una función con una firma de () -> T , lo que significa que no toma parámetros y devuelve algo de tipo T Las referencias de método que proporcione como argumentos deben seguir esa firma para que se pasen.

Si desea crear un Supplier<Foo> que funcione con el constructor, puede usar el método de enlace general que sugiere @Tagir Valeev, o puede hacer uno más especializado.

Si desea un Supplier<Foo> que siempre use esa Cadena "hello" , puede definirla de dos maneras diferentes: como un método o una variable Supplier<Foo> .

método:

static Foo makeFoo() { return new Foo("hello"); }

variable:

static Supplier<Foo> makeFoo = () -> new Foo("hello");

Puede pasar el método con una referencia de método ( create(WhateverClassItIsOn::makeFoo); ), y la variable se puede pasar simplemente usando el nombre create(WhateverClassItIsOn.makeFoo); .

El método es un poco más preferible porque es más fácil de usar fuera del contexto de ser pasado como referencia de método, y también se puede usar en el caso de que alguien requiera su propia interfaz funcional especializada que también es () -> T or is () -> Foo específicamente.

Si desea usar un Supplier que pueda tomar cualquier Cadena como argumento, debe usar algo como el método de enlace que @Tagir mencionó, evitando la necesidad de suministrar la Function :

Supplier<Foo> makeFooFromString(String str) { return () -> new Foo(str); }

Puede pasar esto como un argumento como este: create(makeFooFromString("hello"));

Aunque, tal vez deberías cambiar todas las llamadas "hacer ..." a las llamadas "suministrar ...", solo para hacerlo un poco más claro.


Pero, un constructor de 1 argumento para T que toma una String es compatible con la Function<String,T> :

Function<String, Foo> fooSupplier = Foo::new;

El constructor seleccionado se trata como un problema de selección de sobrecarga, en función de la forma del tipo de destino.


Si le gustan tanto las referencias de métodos, puede escribir un método de bind usted mismo y usarlo:

public static <T, R> Supplier<R> bind(Function<T,R> fn, T val) { return () -> fn.apply(val); } create(bind(Foo::new, "hello"));