多态(
Polymorphism
)按字面的意思就是"多种状态"
. 在面向对象语言中, 接口的多种不一样的实现方式
即为多态. 多态性是容许你将父对象设置成为一个或更多的他的子对象相等的技术, 赋值以后, 父对象就能够根据当前赋值给它的子对象的特性以不一样的方式运做. 简单的说, 就是一句话: 容许将子类类型的指针赋值给父类类型的指针. 多态性在Object Pascal和C++中都是经过虚函数实现的.git
多太是单一接口接受不一样类型的技术. 根本上, 它容许不一样的数据类型适用于相同的函数. 不一样类型的
相同函数形态完成相同的行为
. Elixir 适用协议(Protocols
)实现多太.github
下面以一个温度的不一样表示形式来讲明如何在开发过程当中使用多太.编程
# 开尔文 defmodule Kelvin do defstruct name: "Kelvin", symbol: "K", degree: 0 end # 华氏温度 defmodule Fahrenheit do defstruct name: "Fahrenheit", symbol: "°F", degree: 0 end # 摄氏温度 defmodule Celsius do defstruct name: "Celsius", symbol: "°C", degree: 0 end # 温度协议(接口, 只有函数定义, 没有函数实现) defprotocol Temperature do @doc """ Convert Kelvin and Fahrenheit to Celsius degree """ def to_celsius(degree) end # 开尔文, 实现了Temperature 协议(接口) defimpl Temperature, for: Kelvin do @doc """ Deduct 273.15 """ def to_celsius(kelvin) do celsius_degree = kelvin.degree - 273.15 %Celsius{degree: celsius_degree} end end # 华氏摄氏度实现 defimpl Temperature, for: Fahrenheit do @doc """ Deduct 32, then multiply by 5, then divide by 9 """ def to_celsius(fahrenheit) do celsius_degree = (fahrenheit.degree - 32) * 5 / 9 %Celsius{degree: celsius_degree} end end
下面是实际的运行结果编程语言
iex> fahrenheit = %Fahrenheit{degree: 45} %Fahrenheit{degree: 45, name: "Fahrenheit", symbol: "°F"} iex> celsius = Temperature.to_celsius(fahrenheit) %Celsius{degree: 7.22, name: "Celsius", symbol: "°C"} iex> kelvin = %Kelvin{degree: 300} %Kelvin{degree: 300, name: "Kelvin", symbol: "K"} iex> celsius = Temperature.to_celsius(kelvin) %Celsius{degree: 26.85, name: "Celsius", symbol: "°C"}
上面的代码, 并无实现摄氏温度模块. 你能够试着本身实现.ide
iex> Temperature.to_celsius(%{degree: 12}) ** (Protocol.UndefinedError) protocol Temperature not implemented for %{degree: 12} iex:11: Temperature.impl_for!/1 iex:15: Temperature.to_celsius/1
若是想深刻了解Elixir的多态, 能够参考Elixir内置模块 String.Char 和 Enum 的实现. 函数
经过阅读 Enum 模块的源码, 你能够了解到, Enum 模块是如何处理不一样的数据类型的.spa
多态本质上是一种运行时动态技术, 能够想象一下变量的概念, 若是编程语言中没有变量(多态, 接口), 只有常量(具体实现类), 那编程会是一种什么样的体验?指针