Interfaces in Nim
Our first example demonstrates interfaces, which are named collections of method signatures.
import math
# Here's a basic interface for geometric shapes.
type
Geometry = concept
proc area(self: Self): float
proc perim(self: Self): float
# For our example we'll implement this interface on
# `Rect` and `Circle` types.
type
Rect = object
width, height: float
Circle = object
radius: float
# To implement an interface in Nim, we just need to
# implement all the methods in the interface. Here we
# implement `Geometry` on `Rect`s.
proc area(r: Rect): float =
r.width * r.height
proc perim(r: Rect): float =
2*r.width + 2*r.height
# The implementation for `Circle`s.
proc area(c: Circle): float =
math.PI * c.radius * c.radius
proc perim(c: Circle): float =
2 * math.PI * c.radius
# If a variable has an interface type, then we can call
# methods that are in the named interface. Here's a
# generic `measure` function taking advantage of this
# to work on any `Geometry`.
proc measure(g: Geometry) =
echo g
echo g.area()
echo g.perim()
# Main function
proc main() =
let r = Rect(width: 3, height: 4)
let c = Circle(radius: 5)
# The `Circle` and `Rect` types both
# implement the `Geometry` interface so we can use
# instances of these types as arguments to `measure`.
measure(r)
measure(c)
main()
To run the program, save it as interfaces.nim
and use the Nim compiler:
$ nim c -r interfaces.nim
{width: 3.0, height: 4.0}
12.0
14.0
{radius: 5.0}
78.53981633974483
31.41592653589793
In this Nim example, we’ve implemented the concept of interfaces using Nim’s concept
feature. The Geometry
concept defines the required methods for any type that wants to be considered a geometric shape.
We then define Rect
and Circle
types and implement the required methods for each. The measure
function demonstrates how we can use any type that satisfies the Geometry
concept.
Nim’s approach to interfaces (concepts) is more flexible than Go’s, as it uses structural typing rather than nominal typing. This means that types don’t need to explicitly declare that they implement an interface; they just need to have the required methods.
To learn more about Nim’s concepts and how they compare to interfaces in other languages, check out the Nim documentation on concepts.