¿Qué es un ejemplo de pato escribiendo en Java?
text field java (10)
Acabo de enterarme de escribir patos y leí el artículo de Wikipedia al respecto, pero me cuesta mucho traducir los ejemplos a Java, lo que realmente me ayudaría a comprenderlo.
¿Alguien podría dar un ejemplo claro de pato escribiendo en Java y cómo podría usarlo?
Buena definición:
Los objetos son polimórficos sin estar relacionados por una clase base común o interfaz.
Con java 8, tienes 2 formas:
nº1: si solo necesitas un método, utiliza lambdas
static interface Action { public int act(); }
public int forEachAct(List<Action> actionlist) {
int total = 0;
for (Action a : actionList)
total += a.act();
}
public void example() {
List<Action> actionList = new ArrayList<>();
String example = "example";
actionList.add(example::length);
forEachAct(actionList);
}
nº2: utiliza clases anónimas (no muy en cuanto a rendimiento, pero en algunas partes no críticas se puede hacer)
static interface Action {
public int act();
public String describe();
}
public void example() {
List<Action> actionList = new ArrayList<>();
String example = "example";
actionList.add(new Action(){
public int act() { return example.length(); }
public String describe() { return "Action: " + example; }
});
}
Escribí una clase de utilidad para crear decoradores dinámicamente para un objeto. Podrías usarlo para tipar patos: https://gist.github.com/stijnvanbael/5965616
Ejemplo:
interface Quacking {
void quack();
}
class Duck {
public void quack() { System.out.println("Quack!"); }
}
class Frog {
public void quack() { System.out.println("Ribbip!"); }
}
Quacking duck = Extenter.extend(new Duck()).as(Quacking.class);
Quacking frog = Extenter.extend(new Frog()).as(Quacking.class);
duck.quack();
frog.quack();
Salida:
Quack!
Ribbip!
Escribir en Java es nominal: la compatibilidad se basa en nombres. Si necesita un ejemplo de cómo se puede ver el tipado de pato (o tipado estructural) en Java, mire esta página: http://whiteoak.sourceforge.net/#Examples que proporciona ejemplos para el programa escrito en Whiteoak: A Java- lenguaje compatible que también es compatible con la tipificación estructural.
Java no implementa la tipificación de pato.
Por definición, Java no es apto para el tipado de patos. La forma en que puedes elegir hacerlo es reflexionar:
public void doSomething(Object obj) throws Exception {
obj.getClass().getMethod("getName", new Class<?>[] {}).invoke(obj);
}
Pero recomendaría hacerlo en un lenguaje dinámico, como Groovy, donde tiene más sentido:
class Duck {
quack() { println "I am a Duck" }
}
class Frog {
quack() { println "I am a Frog" }
}
quackers = [ new Duck(), new Frog() ]
for (q in quackers) {
q.quack()
}
Por lo general, la tipificación de pato se usa con lenguajes tipados dinámicamente. Comprobaría en el tiempo de ejecución la existencia de métodos o propiedades necesarios para satisfacer sus necesidades, independientemente de las jerarquías de herencia.
Además de usar el reflejo, que se pondría feo, lo más cercano que puede obtener es mediante el uso de interfaces mínimas que coincidan con los criterios de lo que necesitaría para el tipado de pato. Esta publicación de blog hace un buen trabajo describiendo el concepto. Pierde gran parte de la simplicidad del pato al escribir en python o ruby o javascript, pero en realidad es una práctica bastante buena en Java si está buscando un alto nivel de reutilización.
Tarde a la fiesta (como de costumbre), pero escribí una clase rápida para hacer algo de pato escribiendo yo mismo. Mira here .
Solo irá a las interfaces, pero para un ejemplo de uso:
interface Bird {
void fly();
}
interface Duck extends Bird {
void quack();
}
class PseudoDuck {
void fly() {
System.out.println("Flying");
}
void quack() {
System.out.println("Quacking");
}
}
class Tester {
@Test
void testDuckTyping() {
final Duck duck
= DuckTyper.duckType(new PseudoDuck(), Duck.class);
}
}
Admite métodos de interfaz predeterminados, parámetros, comprobación Los tipos de excepción son compatibles y verificará todos los métodos de la clase del PseudoDuck (incluido el privado). Sin embargo, aún no hemos hecho ninguna prueba con interfaces genéricas.
Vea esta publicación en el blog . Proporciona una descripción muy detallada de cómo usar los proxies dinámicos para implementar el tipado de pato en Java.
En resumen:
- crea una interfaz que represente los métodos que deseas usar mediante el tipado de patos
- crear un proxy dinámico que use esta interfaz y un objeto de implementación que invoca métodos de la interfaz en el objeto subyacente por reflexión (suponiendo que las firmas coincidan)
interface MyInterface {
void foo();
int bar(int x, int y);
int baz(int x);
}
public class Delegate {
public int bar() {
return 42;
}
}
DuckPrxy duckProxy = new DuckPrxyImpl();
MyInterface prxy = duckProxy.makeProxy(MyInterface.class, new Delegate());
prxy.bar(2, 3); // Will return 42.
Con una interfaz, el tipado de pato es simple usando un Proxy dinámico , debe coincidir con el nombre del método y el tipo de retorno.