什么是 Java 中鸭子类型的示例?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/1079785/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-29 15:05:40  来源:igfitidea点击:

What's an example of duck typing in Java?

javaduck-typing

提问by Cuga

I just recently heard of duck typing and I read the Wikipedia articleabout it, but I'm having a hard time translating the examples into Java, which would really help my understanding.

我最近刚听说过鸭子打字,我阅读了关于它的维基百科文章,但我很难将这些例子翻译成 Java,这真的有助于我的理解。

Would anyone be able to give a clear example of duck typing in Java and how I might possibly use it?

谁能给出一个清晰的 Java 中鸭子类型的例子,以及我可能如何使用它?

回答by Robert Munteanu

Java is by design not fit for duck typing. The way you might choose to do it is reflection:

Java 的设计不适合鸭子类型。您可能选择的方式是反射:

public void doSomething(Object obj) throws Exception {

    obj.getClass().getMethod("getName", new Class<?>[] {}).invoke(obj);
}

But I would advocate doing it in a dynamic language, such as Groovy, where it makes more sense:

但我会提倡用动态语言来做,比如 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()
}

Reference

参考

回答by Dean Povey

See this blog post. It gives a very detailed account of how to use dynamic proxies to implement duck typing in Java.

请参阅此博客文章。它非常详细地介绍了如何使用动态代理在 Java 中实现鸭子类型。

In summary:

总之:

  • create an interface that represents the methods you want to use via duck typing
  • create a dynamic proxy that uses this interface and an implementation object that invokes methods of the interface on the underlying object by reflection (assuming the signatures match)
  • 创建一个接口,表示您要通过鸭子类型使用的方法
  • 创建一个使用此接口的动态代理和一个实现对象,该对象通过反射调用底层对象上的接口方法(假设签名匹配)

回答by dfa

check this library:

检查这个库

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.

With an interface duck typing is simple using a Dynamic Proxy, you should match the method name and return type.

使用Dynamic Proxy接口鸭子类型很简单,您应该匹配方法名称和返回类型。

回答by cd1

Java doesn't implement duck typing.

Java 没有实现鸭子类型。

回答by JavaJavaDingDingDing

With java 8, you have 2 ways:

使用 java 8,您有两种方法:

no1: if you only need one method, use lambdas

no1:如果您只需要一种方法,请使用 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);
}

no2: Use anonymous classes (not very performance-wise, but in some non-critical parts it can be done)

no2:使用匿名类(不是很注重性能,但在一些非关键部分可以做到)

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; }
    });
}

回答by Suganthan Madhavan Pillai

Nice definition:

不错的定义:

Objects are polymorphic without being related by a common base class or interface.

对象是多态的,与公共基类或接口无关。

Reference

参考

回答by Stijn Van Bael

I've written a utility class to dynamically create decorators for an object. You could use it for duck typing: https://gist.github.com/stijnvanbael/5965616

我编写了一个实用程序类来为对象动态创建装饰器。你可以用它来打鸭子:https: //gist.github.com/stijnvanbael/5965616

Example:

例子:

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();

Output:

输出:

Quack!
Ribbip!

回答by BeUndead

Late to the party (as usual), but I wrote a quick class for doing some duck typing myself. See here.

聚会迟到(像往常一样),但我写了一个快速课程,让我自己做一些鸭子打字。见这里

It will only go to interfaces, but for a usage example:

它只会转到接口,但举个例子:

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);
    }
}

Supports default interface methods, parameters, checking Exception types are compatible and will check allmethods of the PseudoDuck's class (including private). Haven't done any testing with generic interfaces yet though.

支持默认接口方法,参数,检查异常类型是否兼容,会检查PseudoDuck类的所有方法(包括private)。不过还没有对通用接口进行任何测试。

回答by Itay Maman

Typing in Java is nominal - compatibility is based on names. If you need an examples on how duck-typing (or structural typing) may look like in Java please look at this page: http://whiteoak.sourceforge.net/#Exampleswhich provides examples for program written in Whiteoak: A Java-compatible language that also supports structural typing.

在 Java 中打字是名义上的 - 兼容性基于名称。如果您需要有关鸭子类型(或结构类型)在 Java 中的样子的示例,请查看此页面:http://whiteoak.sourceforge.net/#Examples,其中提供了用 Whiteoak 编写的程序示例:A Java-也支持结构类型的兼容语言。

回答by Russell Leggett

Typically, duck typing is used with dynamically typed languages. You would check at runtime for the existence of methods or properties that are required to fulfill your needs, regardless of inheritance hierarchies.

通常,鸭子类型与动态类型语言一起使用。您将在运行时检查是否存在满足您的需求所需的方法或属性,而不管继承层次结构如何。

Other than using reflection, which would get ugly, the closest you can get is by using minimal interfaces that match the criteria of what you would need for duck typing. This blog postdoes a good job describing the concept. It loses much of the simplicity of duck typing in python or ruby or javascript, but its actually pretty good practice in Java if you're looking for a high level of reusability.

除了使用反射会变得丑陋之外,您可以获得的最接近的方法是使用与鸭子类型所需的标准相匹配的最少接口。这篇博文很好地描述了这个概念。它失去了在 python、ruby 或 javascript 中输入鸭子的大部分简单性,但如果您正在寻找高水平的可重用性,它实际上在 Java 中是非常好的实践。