Elixir - Protocolos

Los protocolos son un mecanismo para lograr polimorfismo en Elixir. El envío en un protocolo está disponible para cualquier tipo de datos siempre que implemente el protocolo.

Consideremos un ejemplo de uso de protocolos. Usamos una función llamadato_stringen los capítulos anteriores para convertir de otros tipos al tipo de cadena. Este es en realidad un protocolo. Actúa de acuerdo con la entrada que se da sin producir error. Esto puede parecer que estamos discutiendo funciones de coincidencia de patrones, pero a medida que avanzamos, resulta diferente.

Considere el siguiente ejemplo para comprender mejor el mecanismo del protocolo.

Creemos un protocolo que mostrará si la entrada dada está vacía o no. Llamaremos a este protocoloblank?.

Definición de un protocolo

Podemos definir un protocolo en Elixir de la siguiente manera:

defprotocol Blank do
   def blank?(data)
end

Como puede ver, no es necesario definir un cuerpo para la función. Si está familiarizado con las interfaces en otros lenguajes de programación, puede pensar en un Protocolo como esencialmente lo mismo.

Así que este Protocolo dice que todo lo que lo implemente debe tener un empty?función, aunque depende del implementador cómo responde la función. Con el protocolo definido, entendamos cómo agregar un par de implementaciones.

Implementar un protocolo

Ya que hemos definido un protocolo, ahora necesitamos decirle cómo manejar las diferentes entradas que podría recibir. Construyamos sobre el ejemplo que habíamos tomado anteriormente. Implementaremos el protocolo en blanco para listas, mapas y cadenas. Esto mostrará si lo que pasamos está en blanco o no.

#Defining the protocol
defprotocol Blank do
   def blank?(data)
end

#Implementing the protocol for lists
defimpl Blank, for: List do
   def blank?([]), do: true
   def blank?(_), do: false
end

#Implementing the protocol for strings
defimpl Blank, for: BitString do
   def blank?(""), do: true
   def blank?(_), do: false
end

#Implementing the protocol for maps
defimpl Blank, for: Map do
   def blank?(map), do: map_size(map) == 0
end

IO.puts(Blank.blank? [])
IO.puts(Blank.blank? [:true, "Hello"])
IO.puts(Blank.blank? "")
IO.puts(Blank.blank? "Hi")

Puede implementar su Protocolo para tantos o tan pocos tipos como desee, lo que tenga sentido para el uso de su Protocolo. Este fue un caso de uso bastante básico de protocolos. Cuando se ejecuta el programa anterior, produce el siguiente resultado:

true
false
true
false

Note - Si usa esto para cualquier otro tipo que no sea el que definió el protocolo, producirá un error.