Каков пример утиной печати на Java?
Я недавно слышал о наборе уток, и я прочитал статью в Википедии об этом, но мне сложно перевести примеры на Java, что действительно помогло бы мне понять.
Кто-нибудь сможет дать ясный пример утиной печати на Java и как я могу ее использовать?
- javafx, используя объекты MainController или других controllerов в соответствующем classе controllerа
- @Автоматический и статический метод
- Java: инициализировать несколько переменных для цикла init?
- Где находится JAVA_HOME на macOS Sierra (10.12), Эль Капитан (10.11), Йосемити (10.10), Маверикс (10.9), Горный лев (10.8) или Лекс OSX (10.7)?
- Java - прокрутите до определенного текста внутри JTextArea
- Итерация через список в обратном порядке в java
- Невозможно добавить значение в коллекцию Java с подстановочным общим типом
- Что такое переменная тень, используемая в classе Java?
- Selenium WebDriver: Подождите, пока сложная страница с JavaScript для загрузки
- Как добавить гиперссылку в JLabel
- Как я могу поместить целое число с нулями слева?
- В чем разница между JVM, JDK, JRE и OpenJDK?
- Как я могу сделать запрос POST с помощью multipart / form-data с использованием Java?
Java по дизайну не подходит для утиной печати. То, как вы можете это сделать, – это reflection:
public void doSomething(Object obj) throws Exception { obj.getClass().getMethod("getName", new Class[] {}).invoke(obj); }
Но я бы защищал это на динамическом языке, таком как Groovy, где это имеет смысл:
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() }
Справка
См. Это сообщение в блоге . Он дает очень подробный отчет о том, как использовать динамические прокси для реализации утиного ввода в Java.
В итоге:
- создать интерфейс, который представляет методы, которые вы хотите использовать с помощью утиной печати
- создайте динамический прокси-сервер, который использует этот интерфейс и объект реализации, который вызывает методы интерфейса на базовом объекте путем отражения (при условии соответствия подписей)
проверьте эту библиотеку :
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.
С помощью утиного ввода интерфейса просто использовать динамический прокси , вы должны сопоставить имя метода и тип возвращаемого значения.
Java не реализует утиную печать.
С java 8 у вас есть 2 способа:
nº1: если вам нужен только один метод, используйте lambda
static interface Action { public int act(); } public int forEachAct(List actionlist) { int total = 0; for (Action a : actionList) total += a.act(); } public void example() { List actionList = new ArrayList<>(); String example = "example"; actionList.add(example::length); forEachAct(actionList); }
nº2: используйте анонимные classы (не очень эффективные, но в некоторых некритических частях это можно сделать)
static interface Action { public int act(); public String describe(); } public void example() { List actionList = new ArrayList<>(); String example = "example"; actionList.add(new Action(){ public int act() { return example.length(); } public String describe() { return "Action: " + example; } }); }
Ввод текста на Java является номинальным – совместимость основана на именах. Если вам нужны примеры того, как может выглядеть утка (или структурная типизация) в Java, посмотрите эту страницу: http://whiteoak.sourceforge.net/# Примеры, в которых приводятся примеры для программы, написанной в Whiteoak: Java- совместимый язык, который также поддерживает структурную типизацию.
Как правило, утиная печать используется с динамически типизированными языками. Вы проверяете во время выполнения наличие методов или свойств, необходимых для удовлетворения ваших потребностей, независимо от иерархии наследования.
Помимо использования рефлексии, которая будет казаться уродливой, самое близкое, что вы можете получить, – это использование минимальных интерфейсов, которые соответствуют критериям того, что вам нужно для утиной печати. Это сообщение в блоге хорошо описывает эту концепцию. Он теряет большую часть простоты утиного ввода в python или ruby или javascript, но на самом деле это довольно хорошая практика на Java, если вы ищете высокий уровень повторного использования.
Хорошее определение:
Объекты являются полиморфными, не связанными с общим базовым classом или интерфейсом.
Справка
Я написал class утилиты для динамического создания декораторов для объекта. Вы можете использовать его для печати уток: https://gist.github.com/stijnvanbael/5965616
Пример:
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();
Вывод:
Quack! Ribbip!
Поздно к вечеринке (как обычно), но я написал быстрый class для того, чтобы сделать какую-то утку, набирая себя. См. Здесь .
Он будет работать только с интерфейсами, но для примера использования:
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); } }
Поддерживает методы интерфейса по умолчанию, параметры, проверку Типы исключений совместимы и будут проверять все методы classа PseudoDuck (включая частные). Тем не менее, тестирование не проводилось с использованием общих интерфейсов.