Ad-hoc polymorphism is a kind of polymorphism that uses types
and polymorphic functions
(aka function overloading) to change the function behavior depending on the types of its arguments.
While behaviour
and defprotocol
are preferred options for achieving polymorphism in Elixir, there is also one more option, probably more simplistic. Ad-hoc polymorphism can be achieved in Elixir using a combination of plain structs, function overloading, pattern matching and destructuring.
First step is to wrap the state, that needs polymorphic behavior in a struct, as shown below.
defmodule ConnectionHandler.FirstConnectionHandler do
defstruct con: nil
end
defmodule ConnectionHandler.SecondConnectionHandler do
defstruct con: nil
end
Then create a module which will house the overloaded functions, that would pattern match over the structs that we just created.
defmodule ConnectionHandler do
alias ConnectionHandler.FirstConnectionHandler
alias ConnectionHandler.SecondConnectionHandler
def handle(%FirstConnectionHandler{con: con}) do
"First"
end
def handle(%SecondConnectionHandler{con: con}) do
"Second"
end
end
Below shown simple test case demonstrates how it all glues together.
defmodule ConnectionHandler.Test do
use ExUnit.Case
defmodule ConnectionHandler.FirstConnectionHandler do
defstruct con: nil
end
defmodule ConnectionHandler.SecondConnectionHandler do
defstruct con: nil
end
defmodule ConnectionHandler do
alias ConnectionHandler.FirstConnectionHandler
alias ConnectionHandler.SecondConnectionHandler
def handle(%FirstConnectionHandler{con: con}) do
"First"
end
def handle(%SecondConnectionHandler{con: con}) do
"Second"
end
end
test "ad-hoc polymorphism demonstration" do
alias ConnectionHandler.FirstConnectionHandler
alias ConnectionHandler.SecondConnectionHandler
assert ConnectionHandler.handle(%FirstConnectionHandler{con: []}) == "First"
assert ConnectionHandler.handle(%SecondConnectionHandler{con: []}) == "Second"
end
end
While this is a way of achieving polymorphism in Elixir, one might want to consider more idiomatic approach of using defprotocol.
Update: Part 2 of this series demonstrates how using defprotocol
retults in better encapsulation and fewer lines of code.
Top comments (0)