Buscar..


Introducción

El polimorfismo es la provisión de una interfaz única para entidades de diferentes tipos. Básicamente, permite que diferentes tipos de datos respondan a la misma función. Entonces, la misma función da forma a diferentes tipos de datos para lograr el mismo comportamiento. El lenguaje elixir tiene protocols para implementar el polimorfismo de una manera limpia.

Observaciones

Si desea cubrir todos los tipos de datos, puede definir una implementación para Any tipo de datos. Por último, si tiene tiempo, verifique el código fuente de Enum y String.Char , que son buenos ejemplos de polimorfismo en el núcleo Elixir.

Polimorfismo con Protocolos

Implementemos un protocolo básico que convierta las temperaturas de Kelvin y Fahrenheit a 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

Ahora, implementamos nuestros convertidores para los tipos Kelvin y Fahrenheit. Hagamos algunas conversiones:

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

Intentemos convertir cualquier otro tipo de datos que no tenga implementación para la función 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
Licenciado bajo CC BY-SA 3.0
No afiliado a Stack Overflow