“当看到一只鸟走起来像鸭子、游泳起来像鸭子、叫起来也像鸭子,那么这只鸟就可以被称为鸭子。“【引用维基】

一般而言,鸭子类型机制常见/用于动态语言,如Python、Ruby、JS。来段Python代码实例:

class Duck:

def quack(self):

print "Quaaaaaack!"

def feathers(self):

print "The duck has white and gray feathers."

class Person:

def quack(self):

print "The person imitates a duck."

def feathers(self):

print "The person takes a feather from the ground and shows it."

def in_the_forest(duck):

duck.quack()

duck.feathers()

def game():

donald = Duck()

john = Person()

in_the_forest(donald)

in_the_forest(john)

game()

从上面代码片段可以看出,鸭子类型设计风格更关注对象的使用,如正则(非成员)函数in_the_forest的形参duck,只要有方法quack和feathers即可,不用关注具体类型,这样使设计更加”范化“。当然鸭子类型机制并不仅限动态语言,在静态语言中也可见,本文主要阐述在Java中的鸭子类型机制(亦称潜在类型机制或结构化类型机制)实现。

实现方式一: 使用一个类或接口,并用有边界泛型方法实现,见代码:

// interface Performs.class

public interface Performs {

void quack();

void feathers();

}

// class Duck.class

public class Duck implements Performs {

public void quack() {

System.out.println("Quaaaaak!");

}

public void feathers() {

System.out.println("The duck has white and gry feathers!");

}

}

// class Person.class

public class Person implements Performs {

public void quack() {

System.out.println("The person imitates a duck!");

}

public void feathers() {

System.out.println("The person has yellow feather!");

}

}

// class MainClass.class

public class MainClass {

public static void inTheForest(T duck) {

duck.quack();

duck.feathers();

}

public static void main(String[] args) {

Duck d = new Duck();

Person p = new Person();

MainClass.inTheForest(d);

MainClass.inTheForest(p);

}

}方式一使用的前提是都有共同的基类或者接口,但是当两个类之间没有这个条件仅有相同的方法签名时如何实现呢?这时可以采用如下两种方法:

方式二: 利用反射,见代码

// class Duck.class

public class Duck {

public void quack() {

System.out.println("Quaaaaak!");

}

public void feathers() {

System.out.println("The duck has white and gry feathers!");

}

}

// class Person.class

public class Person {

public void quack() {

System.out.println("The person imitates a duck!");

}

public void feathers() {

System.out.println("The person has yellow feather!");

}

}

// class MainClass.class

import java.lang.reflect.*;

public class MainClass {

public static void inTheForest(Object duck) {

Class> duk = duck.getClass();

try {

try {

Method quack = duk.getMethod("quack");

quack.invoke(duck);

} catch(NoSuckMethodException e) {

System.err.println(duck + " cannot quack");

}

try {

Method feathers = duk.getMethod("feathers");

feathers.invoke(duck);

} catch(NoSuckMethodException e) {

System.err.println(duck + " cannot feathers");

}

} catch(Exception e) {

throw new RuntimeException(duck.toString(), e);

}

}

public static void main(String[] args) {

Duck d = new Duck();

Person p = new Person();

MainClass.inTheForest(d);

MainClass.inTheForest(p);

}

}

方式三: 模拟接口,使用适配器设计模式

import java.lang.reflect.InvocationTargetException;

import java.lang.reflect.Method;

// interface Performs.class

// 先前不包含这个接口,也不继承这个接口

interface Performs {

void quack();

void feathers();

}

// class Duck.class

class Duck {

public void quack() {

System.out.println("Quaaaaak!");

}

public void feathers() {

System.out.println("The duck has white and gry feathers!");

}

}

// class Person.class

class Person {

public void quack() {

System.out.println("The person imitates a duck!");

}

public void feathers() {

System.out.println("The person has yellow feather!");

}

}

// Adapter

class PerformsAdapter implements Performs {

private Object d;

public PerformsAdapter(Object d) {

this.d = d;

}

public void quack() {

Class> dk = d.getClass();

try {

Method qk = dk.getMethod("quack");

qk.invoke(d);

} catch (NoSuchMethodException e) {

System.out.println(d + " cannot quack");

} catch (InvocationTargetException e) {

e.printStackTrace();

} catch (IllegalAccessException e) {

e.printStackTrace();

}

}

public void feathers() {

Class> dk = d.getClass();

try {

Method ft = dk.getMethod("feathers");

ft.invoke(d);

} catch (NoSuchMethodException e) {

System.out.println(d + " cannot have feathers");

} catch (InvocationTargetException e) {

e.printStackTrace();

} catch (IllegalAccessException e) {

e.printStackTrace();

}

}

}

// class  MainClass.class

public class DuckTest {

public static void inTheForest(T duck) {

duck.quack();

duck.feathers();

}

public static void main(String[] args) {

Duck d = new Duck();

Person p = new Person();

DuckTest.inTheForest(new PerformsAdapter(d));

DuckTest.inTheForest(new PerformsAdapter(p));

}

}

参考文献:

1. 鸭子类型 http://zh.wikipedia.org/wiki/%E9%B8%AD%E5%AD%90%E7%B1%BB%E5%9E%8B

2. 《Thinking in Java》

java 鸭子类_Java中实现鸭子类型机制相关推荐

  1. java 继承示例_Java中的继承类型以及示例

    java 继承示例 Prerequisite: Inheritance and its implementation in Java 先决条件: 继承及其在Java中的实现 Java中的继承类型 (T ...

  2. java double 计算_Java中的Double类型计算

    一.问题的提出: 如果我们编译运行下面这个程序会看到什么? public class Test{ public static void main(String args[]){ System.out. ...

  3. java sleep唤醒_Java中的等待唤醒机制—至少50%的工程师还没掌握!

    Java中的等待唤醒机制-至少50%的工程师还没掌握! 发布时间:2019-12-14 01:53, 浏览次数:222 , 标签: Java 这是一篇走心的填坑笔记,自学Java的几年总是在不断学习新 ...

  4. java 通配符 泛型_java中泛型之类型通配符(?)

    实体类 package cn.xy.model; /** * 生物类 * @author xy * */ public class Living { private String name; publ ...

  5. java类加密_Java中常用加密类型

    1.对称加密 image.png 密钥:加解密钥相同 缺点:无法确保密钥被安全传递 常用算法:DES.3DES(TripleDES).AES等 2.非对称加密 image.png image.png ...

  6. java cache教程_Java 中常用缓存Cache机制的实现

    缓存主要可分为二大类: 一.通过文件缓存,顾名思义文件缓存是指把数据存储在磁盘上,不管你是以XML格式,序列化文件DAT格式还是其它文件格式: 二.内存缓存,也就是实现一个类中静态Map,对这个Map ...

  7. Python 语言中的 “鸭子类型”

    Python 语言中的 "鸭子类型" 继承 多态 鸭子类型 不要检查它是不是鸭子.它的叫声像不像鸭子.它的走路姿势像不像鸭子,等等.具体检查什么取决于你想使用语言的哪些行为.(co ...

  8. python中的鸭子类型

    浅层理解 走路像鸭子,说话像鸭子,它就是鸭子 深层理解 指的是面向对中,子类不需要显示的继承某个类,只要有某个的方法和属性,那我就属于这个类 编程语言中的鸭子类型说明 假设有个鸭子类Duck类,有两个 ...

  9. Java如何给Mysql中插入year类型数据

    文章目录 Java如何给Mysql中插入year类型数据 实际问题: 解决方案: 从数据库中读取year类型数据到Java 从Java中往数据库存储year数据 Java如何给Mysql中插入year ...

最新文章

  1. python私有函数
  2. Boston房价PaddlePaddle测试程序
  3. Codeforces Round #232 Editorial Div2-B
  4. 【控制】遗传算法(GA,Genetic Algorithm)及 Matlab 实现
  5. boost::multiprecision模块debug_adaptor相关的测试程序
  6. Characterizing stochastic time series with ordinal networks
  7. react classname多个_React全家桶简介
  8. java scala中传递变长参数
  9. 在html插入数学公式,在网页中显示数学公式
  10. 问题:检测到远端X服务正在运行中(CVE-1999-0526)
  11. 如何解决CPU过热100度自动关机
  12. 计算机一级win7win10,一招win7免费升级成win10系统的简单方法(图文)
  13. 安装Hadoop3.2.1(很多坑)
  14. c# opengl tao
  15. 幂指函数的极限运算法则
  16. 【编程题】【Scratch四级】2021.03 程序优化
  17. 成为大数据工程师需要具备什么能力?发展前景好么
  18. AF1210深信服网关配置
  19. 神马笔记 版本2.0.0——新的旅程
  20. 铂链获美国顶级区块链投资基金 Draper Dragon Digital Fund投资

热门文章

  1. 【深度】小红书的变法方法,分别怎么操作
  2. 谷歌地图倾斜摄影(三维瓦片3dtiles)展示
  3. 怎么样做好自己的服务器防御
  4. 计算机考研考英语作文,The computer计算机英语作文
  5. Spark2.2.0集群搭建部署之【软件准备篇】
  6. CSS display:table属性用法解析
  7. python项目部署
  8. 如何利用多层循环找出对称的3位数数字?
  9. 【爬虫+数据库操作】用pandas将爬取的股票信息存入数据库!
  10. 篮球比赛计时记分电路Proteus仿真说明