用Java打字的例子是什么?

时间:2009-07-03 15:08:15

标签: java duck-typing

我刚刚听说过鸭子打字,我读了Wikipedia article关于它的问题,但是我很难将这些例子翻译成Java,这对我的理解非常有帮助。

是否有人能够提供Java中鸭子类型的明确示例以及我可能如何使用它?

10 个答案:

答案 0 :(得分:43)

Java设计不适合鸭子打字。您可以选择这样做的方式是反思:

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

Reference

答案 1 :(得分:11)

this blog post。它详细介绍了如何使用动态代理在Java中实现鸭子类型。

总结:

  • 创建一个接口,通过duck typing
  • 表示您要使用的方法
  • 创建一个动态代理,使用此接口和一个实现对象,通过反射调用底层对象上的接口方法(假设签名匹配)

答案 2 :(得分:6)

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.

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

答案 3 :(得分:5)

Java没有实现duck typing。

答案 4 :(得分:3)

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

nº1:如果您只需要一种方法,请使用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:使用匿名类(性能不是很好,但在某些非关键部分可以完成)

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

答案 5 :(得分:1)

用Java命名是标称的 - 兼容性基于名称。如果你需要一个关于鸭子打字(或结构类型)在Java中的样子的例子,请看这个页面:http://whiteoak.sourceforge.net/#Examples它提供了用Whiteoak编写的程序的例子:一种兼容Java的语言,它也支持结构类型

答案 6 :(得分:1)

通常,duck typing与动态类型语言一起使用。无论继承层次结构如何,您都会在运行时检查是否存在满足您需求所需的方法或属性。

除了使用会变得难看的反射之外,你可以得到的最接近的是使用符合鸭子打字所需条件的最小接口。这个blog post很好地描述了这个概念。它失去了python或ruby或javascript中鸭子类型的简单性,但如果你正在寻找高水平的可重用性,它在Java中实际上是非常好的做法。

答案 7 :(得分:1)

很好的定义:

对象是多态的,不会被公共基类或接口关联。

Reference

答案 8 :(得分:1)

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

示例:

fetchBatchSize

输出:

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

答案 9 :(得分:1)

晚会(像往常一样),但我写了一个快速课程,自己做一些鸭子打字。请参阅here

它只会转到接口,但是对于一个用法示例:

if ((Model.Version >= 1.2 && Model.Version <= 1.3) || Model.Locale == EnglishSpeaking) 
{
    ...
} 
else if ( Model.Version > 1.3 && Model.Locale == EnglishSpeaking ) 
{ 
    ... 
} 
else if ....

支持默认接口方法,参数,检查异常类型是兼容的,并将检查PseudoDuck类(包括私有)的所有方法。但是,还没有使用通用接口进行任何测试。