Cadence OOPs Mastery: Interface

Interfaces

An interface is an abstract type that specifies the behavior of types that implement the interface. Interfaces declare the required functions and fields, the access control for those declarations, and preconditions and postconditions that implementing types need to provide.

There are three kinds of interfaces:

Structure interfaces: implemented by structures

Resource interfaces: implemented by resources

Contract interfaces: implemented by contracts

In Flow and Cadence, there are two types of access control:

There is no support for event and enum interfaces.

Calling functions with preconditions and postconditions on interfaces instead of concrete implementations can improve the security of a program, as it ensures that even if implementations change, some aspects of them will always hold.

1. Declaration

Interfaces are declared using the struct, resource, or contract keyword, followed by the interface keyword, the name of the interface, and the requirements, which must be enclosed in opening and closing braces.

Neither the `var` keyword, nor the `let` keyword is used, so the field may be implemented as either a variable or as a constant field.

pub resource interface FungibleToken {

init(balance: Int) {

pre {

balance >= 0:

"Balances are always non-negative"

}

}

pub fun deposit(_ token: @{FungibleToken}) {

post {

self.balance == before(self.balance) + token.balance:

"the amount must be added to the balance"

}

}

}

2. Implementation

Declaring that a type implements (conforms) to an interface is done in the type declaration of the composite type (e.g., structure, resource): The kind and the name of the composite type is followed by a colon (:) and the name of one or more interfaces that the composite type implements.

The field declarations in the implementing type must match the field requirements in the interface in terms of name, type, and declaration kind (e.g. constant, variable) if given. For example, an interface may require a field with a certain name and type, but leaves it to the implementation what kind the field is.

3.Interfaces in Types

Interfaces can be used in types: The type {I} is the type of all objects that implement the interface I.

pub struct interface Shape {

pub fun getArea(): Int

pub fun scale(factor: Int)

}

pub struct Rectangle: Shape {

pub var width: Int

pub var height: Int

pub init(width: Int, height: Int) {

self.width = width

self.height = height

}

}

4.Interface Default Functions

Interfaces can provide default functions: If the concrete type implementing the interface does not provide an implementation for the function required by the interface, then the interface's default function is used in the implementation.

Interfaces cannot provide default initializers or default destructors. Only one conformance may provide a default function.

struct interface Container {

let items: [AnyStruct]

fun getCount(): Int {

return self.items.length

}

}