Protocols enable polymorphism in Elixir. Define protocols with defprotocol:
defprotocol Log do
def log(value, opts)
endImplement a protocol with defimpl:
require Logger
# User and Post are custom structs
defimpl Log, for: User do
def log(user, _opts) do
Logger.info "User: #{user.name}, #{user.age}"
end
end
defimpl Log, for: Post do
def log(user, _opts) do
Logger.info "Post: #{post.title}, #{post.category}"
end
endInstead of sharing protocol implementation with maps, structs require their own protocol implementation.
With the above implementations, we can do:
iex> Log.log(%User{name: "Yos", age: 23})
22:53:11.604 [info] User: Yos, 23
iex> Log.log(%Post{title: "Protocols", category: "Protocols"})
22:53:43.604 [info] Post: Protocols, ProtocolsProtocols let you dispatch to any data type, so long as it implements the protocol. This includes some built-in types such as Atom, BitString, Tuples, and others.
Other Examples
Poison allows developers to implement Encoders for their own structs for serializing them to JSON, by implementing the Poison.Encoder protocol.
defimpl Poison.Encoder, for: Person do
def encode(%{name: name, age: age}, options) do
Poison.Encoder.BitString.encode("#{name} (#{age})", options)
end
endAdditional reading: