Elixir Language
Polymorfisme in Elixir
Zoeken…
Invoering
Polymorfisme is het verschaffen van een enkele interface voor entiteiten van verschillende typen. Kort gezegd kunnen verschillende gegevenstypen op dezelfde functie reageren. Dus, dezelfde functie vormt voor verschillende gegevenstypen om hetzelfde gedrag te bereiken. De taal van het Elixer heeft protocols
om polymorfisme op een schone manier te implementeren.
Opmerkingen
Als u alle gegevenstypen wilt dekken, kunt u een implementatie definiëren voor Any
gegevenstype. Ten slotte, als je tijd hebt, controleer dan de broncode van Enum en String.Char , die goede voorbeelden zijn van polymorfisme in kernelixir .
Polymorfisme met protocollen
Laten we een basisprotocol implementeren dat Kelvin- en Fahrenheit-temperaturen omzet in Celsius.
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 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
Nu hebben we onze converters geïmplementeerd voor de types Kelvin en Fahrenheit. Laten we wat conversies maken:
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"}
Laten we proberen een ander gegevenstype te converteren dat geen implementatie heeft voor de functie to_celsius
:
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