البروتوكولات هي آلية لتحقيق تعدد الأشكال في Elixir عندما تريد أن يتغير السلوك حسب نوع البيانات.
تُعرَّف البروتوكولات باستخدام defprotocol وتحتوي على ترويسة دالة واحدة أو أكثر.
defprotocol Reversible do
def reverse(term)
end
يمكن تنفيذ البروتوكولات باستخدام defimpl.
defimpl Reversible, for: List do
def reverse(term) do
Enum.reverse(term)
end
end
يمكن تنفيذ بروتوكول لأي نوع بيانات موجود في Elixir أو لبنية.
عند استدعاء دالة بروتوكول، يتم اختيار التنفيذ المناسب تلقائيًا بناءً على نوع الوسيط الأول.
أنت تطوّر لعبة فيديو لتقمّص الأدوار خاصة بك. في لعبتك، هناك شخصيات و_أغراض_. ومن بين الإجراءات الكثيرة التي يمكنك تنفيذها على غرض ما، أن تجعل شخصية تأكله.
ليست كل الأغراض صالحة للأكل، ولا تُحدث كل الأغراض الصالحة للأكل التأثير نفسه في الشخصية. بعض الأغراض، عند أكلها، تتحول إلى غرض مختلف (مثلًا، إذا أكلت تفاحة، يتبقى لديك لبّ التفاحة).
ولإتاحة كل هذه المرونة، قررت إنشاء بروتوكول Edible يمكن لبعض الأغراض تنفيذه.
أنشئ بروتوكول RPG.Edible. يحتوي البروتوكول على دالة واحدة، وهي eat. تقبل دالة eat غرضًا وشخصية وتُرجع ناتجًا ثانويًا وشخصية.
طبّق بروتوكول RPG.Edible على غرض RPG.LoafOfBread. عند أكله، يمنح رغيف الخبز الشخصية 5 نقاط صحة وليس له ناتج ثانوي.
RPG.Edible.eat(%RPG.LoafOfBread{}, %RPG.Character{health: 31})
# => {nil, %RPG.Character{health: 36, mana: 0}}
طبّق بروتوكول RPG.Edible على غرض RPG.ManaPotion. عند أكلها، تمنح جرعة المانا الشخصية من نقاط المانا بقدر قوة الجرعة، وتنتج زجاجة فارغة.
RPG.Edible.eat(%RPG.ManaPotion{strength: 13}, %RPG.Character{mana: 50})
# => {%RPG.EmptyBottle{}, %RPG.Character{health: 100, mana: 63}}
طبّق بروتوكول RPG.Edible على غرض RPG.Poison. عند أكله، يسلب السم كل نقاط الصحة من الشخصية، وينتج زجاجة فارغة.
RPG.Edible.eat(%RPG.Poison{}, %RPG.Character{health: 3000})
# => {%RPG.EmptyBottle{}, %RPG.Character{health: 0, mana: 0}}
سجّل في Exercism لتتعلّم وتتقن Elixir عبر 58 مفهومًا168 تمرينًا، وإرشاد بشري حقيقي، وكل ذلك مجانًا.