多態(
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
多態本質上是一種運行時動態技術, 能夠想象一下變量的概念, 若是編程語言中沒有變量(多態, 接口), 只有常量(具體實現類), 那編程會是一種什麼樣的體驗?指針