Part 12: Interfaces

A circle and a rectangle both have an area; a price and a temperature can both be printed; a version number and a score can both be put in order. An interface names a piece of behaviour like that, and any type can promise to provide it. This part shows how to declare and keep such a promise, how code written against the promise works for every type that keeps it, and how your own types join in with the language's own machinery: {} placeholders, == and <, square brackets and for loops.

What you will learn

  • Declaring an interface and implementing it with extend Type : Interface.
  • Interface values: one variable, array or loop holding many types, with dynamic dispatch choosing the method.
  • Interface parameters, &I and &var I, and requirements that write with self: &var Self.
  • The standard interfaces Display, Equatable and Comparable, and the Ordering a comparison answers with.
  • Comparing structs, tuples, arrays and variants with ==, field by field, for free.
  • Declaring operators such as +, ==, < and [] for your own types, and the four comparisons derived from two.
  • Making a type walkable by for with Next, and a collection with Iterate.

How a type joins in

flowchart LR
    t(["Your type"]) --> own["interface + extend T : I<br/>a promise the compiler checks<br/>(12.1)"]
    own --> dyn["interface values and parameters<br/>one call, many types<br/>(12.2–12.3)"]
    t --> std["standard interfaces<br/>printed with {}, Equals, Compare<br/>(12.4–12.6)"]
    t --> ops["operator functions<br/>==, +, <, []<br/>(12.7–12.10)"]
    t --> loops["Next and Iterate<br/>walked by for<br/>(12.11–12.12)"]

Lessons

LessonWhat you will learn
12.1Interfacedeclare an interface and implement it for your own types
12.2Interface valuehold any implementing type in one interface value
12.3Interface parameterwrite a function that accepts any type implementing an interface
12.4Displaymake your own type printable with {}
12.5Equatabledefine what it means for two of your values to be equal
12.6Comparabledefine an order for your own type
12.7Structural equalitycompare whole structs and tuples with ==
12.8Operator overloaddefine ==, + and the other operators for your own type
12.9Derived operatordefine one operator and get its partners for free
12.10Indexerlet your own type be indexed with []
12.11Iteratorimplement Next so a type of your own can be used with for
12.12Iterablelet a container hand out an iterator for for

Before you start

Finish Part 11: Ownership — an interface value is a copy of what it holds. The lessons also lean on Method, Extension and Mutable reference from Part 6, on optionals from Part 8 for iterators, and on Propagate from Part 9 for Display. Each lesson's package is in the Examples repository's Interfaces/ folder:

cd Examples/Interfaces/Interface
rux run

After this part

Part 13: Generics writes one function or type for many types at once, and interfaces come straight back as its bounds: <T: Display> accepts any type that keeps the Display promise, checked when the program is compiled rather than dispatched while it runs. After Part 16: Numbers you are ready for the next checkpoint projects, Circle and Quadratic.

For the rules behind this part, see Interfaces, Methods and Comparison operators in the Rux Reference.