Building Polymorphic Systems: What You’ll Learn

Welcome back. In earlier lessons, you learned how protocols enable polymorphism by dispatching on data types, and you also defined behaviours to enforce module contracts. In this lesson, you will put the protocol side of that knowledge into action to build a small, extensible validation system. We will create a protocol, implement it for multiple structs, and run a unified workflow that works across different data types without conditionals.

Define a Protocol and Type-Specific Implementations

Explanation:

  • defprotocol Validator defines a single function, valid?/1. Each data type can supply its own implementation.
  • Email and PhoneNumber are simple structs. Protocol dispatch will use the struct type at runtime.
  • The Email implementation checks for an “@” and a minimum length.
  • The PhoneNumber implementation enforces 10 digits using a regex.
  • Pattern matching in the function heads pulls the needed fields cleanly.

Note: Protocol dispatch is resolved efficiently after compilation (protocol consolidation). You get dynamic behavior with compile-time optimization.

Orchestrate Validation and Run the System

Explanation:

  • validate_contacts/1 iterates over mixed data, calls Validator.valid?/1, and pairs each item with its validation result.
  • The function does not need to know the concrete type. That is the core benefit of polymorphism.

Explanation:

  • You build a mixed list of Email and PhoneNumber structs.
  • ContactValidator.validate_contacts/1 triggers protocol dispatch for each item.
  • The output shows each contact with a true/false result, proving that one call site can handle multiple types without case statements.

Note: This design follows the open/closed principle. To support a new contact type (e.g., Address), define a struct and a defimpl Validator, for: Address, then everything else “just works.”

Summary and Next Steps

You created a protocol, implemented it for two structs, and wired a small workflow that validates mixed data without branching. This is a practical pattern for building flexible systems: keep call sites simple, push type-specific logic into protocol implementations, and add new types by extension, not modification.

Sign up
Join the 1M+ learners on CodeSignal
Be a part of our community of 1M+ users who develop and demonstrate their skills on CodeSignal