प्रोटोकॉल:
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 फंक्शन इस प्रोटोकॉल की मदद से किसी एन्यूमरेबल को किसी कलेक्शन में डालता है।Inspect - इस प्रोटोकॉल को लागू करके आप यह बदल सकते हैं कि Kernel.inspect/2 किसी डेटा टाइप को स्ट्रिंग के रूप में कैसे दिखाता है।String.Chars - इस प्रोटोकॉल को लागू करके आप यह बदल सकते हैं कि Kernel.to_string/1 किसी डेटा टाइप को स्ट्रिंग के रूप में कैसे दिखाता है।