---
title: "Interface"
description: "Experimental interface keyword and implement statement."
---
An `interface` describes a contract that a component can promise to fulfill.
It lists the properties, callbacks, and functions that an implementing component must provide.
This lets you write code that works with any component that implements the interface, without caring about the concrete type.

> **Note**: `interface` and `implement` are experimental and subject to change.
> Tracking issue: [slint-ui/slint#1870](https://github.com/slint-ui/slint/issues/1870).

## Declaring an interface

Use the `interface` keyword followed by a body that lists the contract.

```slint no-test
interface TextInterface {
    in-out property <string> text;

    public pure function length(text: string) -> int;
}
```

An interface body may contain:

- Properties with visibility `in`, `out`, or `in-out`.
  Default values are not permitted.
- Callbacks, with any signature except `init`.
- Function declarations without a body.
  They must be `public` and can be `pure`.

An interface body may **not** contain bindings, child elements, layouts, `states`, two-way bindings, `animate` blocks, or private properties.
An interface can be exported with `export interface`.

## Inheriting an Interface

An interface can extend another with `inherits`:

```slint no-test
interface Named {
    in-out property <string> name;
}

interface Greeter inherits Named {
    callback greet();
}
```

`Greeter`'s contract is `name` and `greet`, so a component implementing `Greeter` must provide both.
An interface can only inherit another interface.

Redeclaring a member the base already declares is an error.
If the base marks the member [`@shadowable`](/guide/experimental/shadowable/), redeclaring it is a warning instead.

## Implementing an interface

A component declares that it implements an interface with an `implement I <=> self;` statement in its body.
The component must declare or inherit every property, callback, and function listed in the interface, matching
type, visibility, and purity. If a member is missing or doesn't match the interface, the compiler reports it as an error.

An `implement` statement's target must be `self` or the id of a child element (see delegation below), and the statement
is only allowed directly in a component's root element, not in a nested child element. `root` and `parent` are not valid
targets: since `implement` is root-only, `root` and `self` refer to the same element there, so use `self` instead.

```slint no-test
export component MyText {
    implement TextInterface <=> self;

    in-out property <string> text <=> input.text;

    input := TextInput {
        text: "Hello";
    }

    public pure function length(text: string) -> int {
        return text.character-count;
    }
}
```

A component can combine `implement` with `inherits`:

```slint no-test
component MyText inherits Rectangle {
    implement TextInterface <=> self;
    // ...
}
```

A component can implement more than one interface, each with its own `implement` statement. Multiple `implement`
statements exposing properties, callbacks or functions with the same name is an error.

## Delegating to a child with `implement <=> child`

Sometimes a component does not implement an interface itself but contains a child that does.
`implement I <=> child-id;` exposes the child's interface on the parent, so users of the parent see the same properties, callbacks, and functions as if the parent implemented the interface directly.

```slint no-test
component Container {
    implement TextInterface <=> inner;
    inner := MyText { }
}
```

The named child must satisfy the interface API (directly or through its own delegation) the listed interface.

## Full example

```slint
interface Counter {
    in-out property <int> value;
    callback increment();
}

component CounterButton {
    // It is not necessary for CounterButton to `implement Counter <=> self;`
    // implement Counter <=> self;

    in-out property <int> value;
    callback increment();

    preferred-width: 100%;
    preferred-height: 100%;

    increment => { value += 1; }
    TouchArea {
        clicked => { root.increment(); }
    }
}

export component App {
    implement Counter <=> button;

    button := CounterButton { }
    Text { text: "Count: \{button.value}"; }
}
```

`App` has a `value` property and an `increment` callback through the `Counter` interface, both provided by `button`.