Interfaces can be used in types: The type {I} is the type of all objects that implement the interface I.
This is called a restricted type: Only the functionality (members and functions) of the interface can be used when accessing a value of such a type.
// Declare an interface named `Shape`.
//
// Require implementing types to provide a field which returns the area,
// and a function which scales the shape by a given factor.
//
pub struct interface Shape {
pub fun getArea(): Int
pub fun scale(factor: Int)
}
// Declare a structure named `Square` the implements the `Shape` interface.
//
pub struct Square: Shape {
// In addition to the required fields from the interface,
// the type can also declare additional fields.
//
pub var length: Int
// Provided the field `area` which is required to conform
// to the interface `Shape`.
//
// Since `area` was not declared as a constant, variable,
// field in the interface, it can be declared.
//
pub fun getArea(): Int {
return self.length * self.length
}
pub init(length: Int) {
self.length = length
}
// Provided the implementation of the function `scale`
// which is required to conform to the interface `Shape`.
//
pub fun scale(factor: Int) {
self.length = self.length * factor
}
}
// Declare a structure named `Rectangle` that also implements the `Shape` interface.
//
pub struct Rectangle: Shape {
pub var width: Int
pub var height: Int
// Provided the field `area which is required to conform
// to the interface `Shape`.
//
pub fun getArea(): Int {
return self.width * self.height
}
pub init(width: Int, height: Int) {
self.width = width
self.height = height
}
// Provided the implementation of the function `scale`
// which is required to conform to the interface `Shape`.
//
pub fun scale(factor: Int) {
self.width = self.width * factor
self.height = self.height * factor
}
}
// Declare a constant that has type `Shape`, which has a value that has type `Rectangle`.
//
var shape: {Shape} = Rectangle(width: 10, height: 20)
Values implementing an interface are assignable to variables that have the interface as their type.
// Assign a value of type `Square` to the variable `shape` that has type `Shape`.
//
shape = Square(length: 30)
// Invalid: cannot initialize a constant that has type `Rectangle`.
// with a value that has type `Square`.
//
let rectangle: Rectangle = Square(length: 10)
Fields declared in an interface can be accessed and functions declared in an interface can be called on values of a type that implements the interface.
// Declare a constant which has the type `Shape`.
// and is initialized with a value that has type `Rectangle`.
//
let shape: {Shape} = Rectangle(width: 2, height: 3)
// Access the field `area` declared in the interface `Shape`.
//
shape.area // is `6`
// Call the function `scale` declared in the interface `Shape`.
//
shape.scale(factor: 3)
shape.area // is `54`