Поиск…


Вступление

Полиморфизм - это предоставление единого интерфейса объектам разных типов. В принципе, он позволяет различным типам данных реагировать на одну и ту же функцию. Таким образом, одни и те же функции формируют разные типы данных для достижения такого же поведения. Язык Elixir имеет protocols для реализации полиморфизма с чистым способом.

замечания

Если вы хотите охватить все типы данных, вы можете определить реализацию для Any типа данных. Наконец, если у вас есть время, проверьте исходный код Enum и String.Char , которые являются хорошими примерами полиморфизма в ядре Elixir.

Полиморфизм с протоколами

Давайте реализуем базовый протокол, который преобразует температуры Кельвина и Фаренгейта в цель.

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

Теперь мы внедрили наши конвертеры для типов Кельвина и Фаренгейта. Давайте сделаем некоторые преобразования:

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"}

Попробуем преобразовать любой другой тип данных, который не имеет реализации для функции 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
Лицензировано согласно CC BY-SA 3.0
Не связан с Stack Overflow