Elixir Language
Polimorfizm w eliksiru
Szukaj…
Wprowadzenie
Polimorfizm jest zapewnianiem jednego interfejsu dla bytów różnego typu. Zasadniczo pozwala różnym typom danych reagować na tę samą funkcję. Tak więc kształty tej samej funkcji dla różnych typów danych pozwalają osiągnąć to samo zachowanie. Język eliksiru ma protocols
do implementacji polimorfizmu w czysty sposób.
Uwagi
Jeśli chcesz objąć wszystkie typy danych, możesz zdefiniować implementację dla Any
typu danych. Na koniec, jeśli masz czas, sprawdź kod źródłowy Enum i String.Char , które są dobrymi przykładami polimorfizmu w rdzeniu Elixir.
Polimorfizm z protokołami
Zaimplementujmy podstawowy protokół, który konwertuje temperatury Kelvina i Fahrenheita na stopnie Celsjusza.
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
Teraz wdrożyliśmy nasze konwertery dla typów Kelvin i Fahrenheit. Zróbmy kilka konwersji:
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"}
Spróbujmy przekonwertować dowolny inny typ danych, który nie ma implementacji dla funkcji 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