پروتکلها عبارتاند از:
defprotocol.defimpl.یکی از نقاط قوت بزرگ پروتکلها این است که پیادهسازی یک پروتکل برای یک نوع دادهی مشخص لازم نیست در کنار تعریف آن نوع داده یا تعریف خود پروتکل قرار بگیرد. این امکان را فراهم میکند که کتابخانههایی نوشته شود که کاربرانشان بتوانند بهراحتی آنها را گسترش دهند تا با انواع دادهی سفارشی خودشان کار کنند، بدون اینکه نیازی به تغییر کتابخانه داشته باشند.
میتوان پروتکلها را برای همهی انواع Elixir پیادهسازی کرد: Tuple، Atom، List، BitString، Integer، Float، Function، PID، Map، Port، Reference، Any و ساختارها.
میتوان پروتکلها را برای چندین نوع بهطور همزمان پیادهسازی کرد:
defimpl Reversible, for: [Map, List] do
def reverse(term) do
Enum.reverse(term)
end
end
وقتی پروتکلی را برای یک ساختار مستقیماً درون ماژولی پیادهسازی میکنید که آن ساختار را تعریف میکند، میتوان آرگومان :for را حذف کرد:
defmodule ShoppingCart do
defstruct [:items]
defimpl Reversible do
def reverse(shopping_cart) do
Enum.reverse(shopping_cart)
end
end
end
Any
بهطور پیشفرض، فراخوانی یک پروتکل برای نوع دادهای که برای آن پیادهسازی نشده است، خطای Protocol.UndefinedError را ایجاد میکند:
to_string({})
# => ** (Protocol.UndefinedError) protocol String.Chars not implemented for {} of type Tuple
# (elixir 1.10.3) lib/string/chars.ex:3: String.Chars.impl_for!/1
# (elixir 1.10.3) lib/string/chars.ex:22: String.Chars.to_string/1
میتوان با ارائهی یک پیادهسازی بازگشتی که در چنین حالتی استفاده میشود، از آن جلوگیری کرد. برای این کار، وقتی پروتکل را تعریف میکنید، ویژگی ماژول @fallback_to_any را روی true قرار دهید و یک پیادهسازی برای نوع Any بنویسید:
defprotocol Reversible do
@fallback_to_any true
def reverse(term)
end
defimpl Reversible, for: Any do
def reverse(term) do
term
end
end
توجه کنید که در بیشتر موارد، ایجاد خطا رویکرد بهتر است، چون دشوار است که فرضی معقول دربارهی یک پروتکل برای همهی انواع داده داشت.
Enumerable - توابع ماژولهای Enum و Stream با انواع دادهای کار میکنند که این پروتکل را پیادهسازی میکنند.Collectable - تابع Enum.into/2 از این پروتکل برای درج یک enumerable در یک مجموعه استفاده میکند.Inspect - میتوانید این پروتکل را پیادهسازی کنید تا نحوهی نمایش یک نوع دادهی مشخص بهصورت رشته توسط Kernel.inspect/2 را تغییر دهید.String.Chars - میتوانید این پروتکل را پیادهسازی کنید تا نحوهی نمایش یک نوع دادهی مشخص بهصورت رشته توسط Kernel.to_string/1 را تغییر دهید.