Διαδρομές
/
Elixir
Elixir
/
Ύλη
/
Πρωτόκολλα
Πρ

Πρωτόκολλα σε Elixir

4 ασκήσεις

Σχετικά με την έννοια Πρωτόκολλα

Τα πρωτόκολλα είναι:

  • Ένας μηχανισμός για την επίτευξη πολυμορφισμού.
  • Ορίζονται με defprotocol.
  • Υλοποιούνται για έναν συγκεκριμένο τύπο δεδομένων με defimpl.

Ένα μεγάλο πλεονέκτημα των πρωτοκόλλων είναι ότι η υλοποίηση ενός πρωτοκόλλου για έναν συγκεκριμένο τύπο δεδομένων δεν χρειάζεται να συνοδεύει τον ορισμό του τύπου δεδομένων ή τον ορισμό του πρωτοκόλλου. Αυτό επιτρέπει τη συγγραφή βιβλιοθηκών που οι χρήστες τους μπορούν εύκολα να επεκτείνουν ώστε να λειτουργούν με τους δικούς τους τύπους δεδομένων, χωρίς να χρειάζεται να τροποποιήσουν τη βιβλιοθήκη.

Υλοποίηση

Μπορείς να υλοποιήσεις πρωτόκολλα για όλους τους τύπους της Elixir: Tuple, Atom, List, BitString, Integer, Float, Function, PID, Map, Port, Reference, Any, και για structs.

Τα πρωτόκολλα μπορούν να υλοποιηθούν για πολλούς τύπους ταυτόχρονα:

defimpl Reversible, for: [Map, List] do
  def reverse(term) do
    Enum.reverse(term)
  end
end

Όταν υλοποιείς ένα πρωτόκολλο για ένα struct απευθείας μέσα σε ένα module που ορίζει το struct, το όρισμα :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 χαρακτηριστικό του module σε 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 - οι συναρτήσεις από τα modules Enum και Stream λειτουργούν με τύπους δεδομένων που υλοποιούν αυτό το πρωτόκολλο.
  • Collectable - η συνάρτηση Enum.into/2 χρησιμοποιεί αυτό το πρωτόκολλο για να εισάγει ένα enumerable σε μια συλλογή.
  • Inspect - μπορείς να υλοποιήσεις αυτό το πρωτόκολλο για να αλλάξεις τον τρόπο με τον οποίο το Kernel.inspect/2 αναπαριστά έναν συγκεκριμένο τύπο δεδομένων ως συμβολοσειρά.
  • String.Chars - μπορείς να υλοποιήσεις αυτό το πρωτόκολλο για να αλλάξεις τον τρόπο με τον οποίο το Kernel.to_string/1 αναπαριστά έναν συγκεκριμένο τύπο δεδομένων ως συμβολοσειρά.
Επεξεργασία μέσω GitHub Ο σύνδεσμος ανοίγει σε νέο παράθυρο ή καρτέλα

Μάθε την έννοια Πρωτόκολλα

Η εξάσκηση είναι κλειδωμένη

Ξεκλείδωσε 1 ακόμη άσκηση για να εξασκηθείς στην έννοια Πρωτόκολλα