Java中鸭子打字的例子是什么?

时间:2023-01-23 22:33:37

I just recently heard of duck typing and I read the Wikipedia article about 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打字输入示例以及我可能如何使用它吗?

10 个解决方案

#1


41  

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

#2


11  

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

看到这篇博文。它详细介绍了如何使用动态代理在Java中实现duck typing。

In summary:

  • create an interface that represents the methods you want to use via duck typing
  • 创建一个接口,通过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)
  • 创建一个使用此接口的动态代理和一个实现对象,该实现对象通过反射调用底层对象上的接口方法(假设签名匹配)

#3


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.

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

使用动态代理,使用接口鸭子输入很简单,您应该匹配方法名称和返回类型。

#4


4  

Java doesn't implement duck typing.

Java没有实现duck typing。

#5


3  

With java 8, you have 2 ways:

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

nº1: if you only need one method, use lambdas

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: Use anonymous classes (not very performance-wise, but in some non-critical parts it can be done)

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

#6


1  

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/#Examples which provides examples for program written in Whiteoak: A Java-compatible language that also supports structural typing.

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

#7


1  

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.

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

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 post does 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中实际上是相当不错的做法。

#8


1  

Nice definition:

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

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

Reference

#9


1  

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!

#10


1  

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 all methods of the PseudoDuck's class (including private). Haven't done any testing with generic interfaces yet though.

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

#1


41  

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

#2


11  

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

看到这篇博文。它详细介绍了如何使用动态代理在Java中实现duck typing。

In summary:

  • create an interface that represents the methods you want to use via duck typing
  • 创建一个接口,通过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)
  • 创建一个使用此接口的动态代理和一个实现对象,该实现对象通过反射调用底层对象上的接口方法(假设签名匹配)

#3


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.

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

使用动态代理,使用接口鸭子输入很简单,您应该匹配方法名称和返回类型。

#4


4  

Java doesn't implement duck typing.

Java没有实现duck typing。

#5


3  

With java 8, you have 2 ways:

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

nº1: if you only need one method, use lambdas

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: Use anonymous classes (not very performance-wise, but in some non-critical parts it can be done)

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

#6


1  

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/#Examples which provides examples for program written in Whiteoak: A Java-compatible language that also supports structural typing.

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

#7


1  

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.

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

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 post does 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中实际上是相当不错的做法。

#8


1  

Nice definition:

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

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

Reference

#9


1  

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!

#10


1  

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 all methods of the PseudoDuck's class (including private). Haven't done any testing with generic interfaces yet though.

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