Interfaces in Crystal
# Interfaces are named collections of method signatures.
# Here's a basic interface for geometric shapes.
module Geometry
abstract def area : Float64
abstract def perim : Float64
end
# For our example we'll implement this interface on
# `Rect` and `Circle` classes.
class Rect
include Geometry
def initialize(@width : Float64, @height : Float64)
end
def area : Float64
@width * @height
end
def perim : Float64
2*@width + 2*@height
end
end
class Circle
include Geometry
def initialize(@radius : Float64)
end
def area : Float64
Math::PI * @radius * @radius
end
def perim : Float64
2 * Math::PI * @radius
end
end
# 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`.
def measure(g : Geometry)
puts g
puts g.area
puts g.perim
end
# In the main function, we create instances of `Rect` and `Circle`
r = Rect.new(width: 3, height: 4)
c = Circle.new(radius: 5)
# The `Circle` and `Rect` classes both
# implement the `Geometry` module so we can use
# instances of these classes as arguments to `measure`.
measure(r)
measure(c)
This Crystal code implements the concept of interfaces using modules. Here’s a breakdown of the translation:
We define a
Geometry
module with abstract methodsarea
andperim
. This is equivalent to thegeometry
interface in the original code.We create
Rect
andCircle
classes that include theGeometry
module and implement its methods.The
measure
function takes a parameter of typeGeometry
, which allows it to work with any object that includes theGeometry
module.In the main part of the program, we create instances of
Rect
andCircle
and pass them to themeasure
function.
To run this program, you would save it to a file (e.g., interfaces.cr
) and then use the Crystal compiler:
$ crystal interfaces.cr
{Rect(@width=3.0, @height=4.0)}
12.0
14.0
{Circle(@radius=5.0)}
78.53981633974483
31.41592653589793
This example demonstrates how Crystal implements interface-like behavior using modules, providing a way to define a set of methods that a class must implement. This allows for polymorphism, where different types can be used interchangeably as long as they implement the required methods.