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


Modified text is an extract of the original Stack Overflow Documentation
Licencjonowany na podstawie CC BY-SA 3.0
Nie związany z Stack Overflow