# Interfaces — a contract several types can satisfy

> An `interface` declares what a type must do without saying how — methods and property contracts, and no state. A member may carry a default body, which an implementor omits or replaces. A class may implement several interfaces alongside its base class, a value typed as the interface accepts any implementor, and the call runs the implementation the value actually holds.

<!-- id: class-interfaces · area: class · stability: stable · html: https://osysharp.com/reference/class/interfaces/ -->

## Summary        {#summary}
An **`interface`** is a contract: what a type must provide, with no state. A member with a body is a **default**.

```osy title="a contract and two implementations" test app=class-interfaces
interface IBlobStore {
  string Put(string key, string body);
  string Name { get; }
}

class S3Store : IBlobStore {
  public string Put(string key, string body) { return "s3://" + key; }
  public string Name { get; } = "s3";
}

class GcsStore : IBlobStore {
  public string Put(string key, string body) { return "gs://" + key; }
  public string Name { get; } = "gcs";
}
```

A value typed as the interface accepts either, and the call runs whichever it holds:

```osy title="the call follows the value, not the slot" test app=class-interfaces
string Upload(IBlobStore store, string key) {
  return store.Put(key, "…");        // "s3://k" or "gs://k" — decided by what `store` IS
}
```

## Signature      {#signature}
```osy syntax
interface IName {
  ReturnType Method(params);         // an obligation to DO something
  Type Property { get; }             // an obligation to ANSWER something
  Type Property { get; set; }        // …and to accept one
  ReturnType Other(params) { … }     // a DEFAULT — an implementor may omit it
  Type Label => …;                   // a default property
}

class Name : Base, IOne, ITwo { … }  // one base class, then any number of contracts
interface IBoth : IOne, ITwo { }     // an interface may extend others
```

Members are **public** without saying so, and **abstract** without saying so unless they have a body — that is what
an interface is.

## Description    {#description}

### Interface or abstract class?    {#which}
Both let you call through a shape rather than a concrete type. Choose by what you need to share:

| | `interface` | `abstract class` |
|---|---|---|
| shared **behaviour** (a body) | a default per member — no fields to work with | yes |
| shared **state** (a field) | no | yes |
| how many a type may have | **many** | one |

An interface is the right default for "these types all do X" — a store, a formatter, a notifier. Reach for an
[abstract class](https://osysharp.com/reference/class/inheritance/) when implementors should share code, not just a shape.

### Implementing one       {#implementing}
A type lists its contracts after its base, and must provide **every** member — the compiler names the ones it is
missing. An inherited implementation counts:

```osy title="the base already answers the contract" test app=class-interfaces
class Logged : S3Store { }           // Put/Name come from S3Store, so `Logged` is an IBlobStore too
```

An `abstract class` may implement a contract **partially** and leave the rest to its subclasses. A member the
contract gives a **default** is not owed at all — see [below](#defaults).

### Can a contract grow without breaking its implementers?    {#defaults}
Yes — give the new member a **default body**. An implementor that does not declare it runs the default; one that
declares it runs its own. This is C# 8's default interface member, and it is how a contract in a package gains a
member without breaking the adapters already written against it:

```osy title="a default the implementor may omit — and one it replaces" test app=class-interfaces-defaults
interface IGreeter {
  string Name { get; }
  string Greet() { return "Hello, " + Name; }     // reads the implementor's own `Name` through `this`
  string Shout() => Greet() + "!";               // a default calling a member one implementor replaced
}

class Plain : IGreeter { public string Name { get; } = "plain"; }

class Custom : IGreeter {
  public string Name { get; } = "custom";
  public string Greet() { return "Hi " + Name; }   // no `override`: a contract member is implemented
}

string Both() {
  IGreeter a = new Plain();
  IGreeter b = new Custom();
  return a.Shout() + " / " + b.Shout();          // "Hello, plain! / Hi custom!"
}
```

A default is reached **through the contract**, as in C#: a class does not inherit its contracts' defaults, so
`new Plain().Greet()` is refused, naming the interface and the way through it (`IGreeter g = new Plain(); g.Greet()`;
inside the class, `IGreeter self = this;`). The call dispatches identically on the server and in the browser.

In a **package**, the version says which kind of change it is: a member added **with** a default is a minor change,
one added **without** breaks every implementor and is a major one — `osy lock` and `osy publish` refuse it under
anything less ([Contracts between kits — an interface in a package, and its version](https://osysharp.com/reference/project/contracts/)).

### Holding and testing one    {#using}
An interface is an ordinary type: a field, a parameter, a return, a collection element. `is` narrows back out of it:

```osy title="a list of contracts, and narrowing out" test app=class-interfaces
string Describe(List<IBlobStore> stores) {
  var s = "";
  foreach (var store in stores) {
    s = s + store.Name;
    if (store is GcsStore) { s = s + "(google)"; }
  }
  return s;
}
```

### What an interface may not do   {#refusals}
Each of these is refused with the reason, not a parse error:

- **It cannot be created.** `new IBlobStore()` has no body to run — create one of the implementors.
- **It holds no state.** A field is refused; a property contract (`int Count { get; }`) is how you require a value.
- **A member that says `abstract` takes no body**, and a `static` member is refused — a default belongs to every
  implementor, a static one to none. Shared STATE belongs on an abstract class.
- **A default is not inherited by the class.** Reach it through the contract (see [above](#defaults)).
- **A missing member is named with its shape** — `'Plain' implements 'IGreeter', which requires 'Name' with no
  default … Add `public string Name { get; }`` — with no `override`, which is for a base class's members.
- **An `entity` implements none.** A row lives in one table told apart by one discriminator; a contract is a
  compile-time promise with nothing to store. Move the behaviour to a `class`.

⚠ **A generic contract cannot be inherited yet** — `class R : IRepo<int>` is refused, and so is `class B : Box<int>`.
That is the generic-inheritance limit, not an interface one; the compiler says so where you write it.

## Examples       {#examples}
Choosing an implementation at run time — the shape this exists for:

```osy title="pick a store, then use it through the contract" test app=class-interfaces
string Store(bool useGcs, string key) {
  IBlobStore store = new S3Store();
  if (useGcs) { store = new GcsStore(); }
  return store.Name + " " + store.Put(key, "payload");
}
```

Two contracts on one type:

```osy title="a type may promise several things" test app=class-interfaces
interface IAudited { string Who(); }

class AuditedS3 : S3Store, IAudited {
  public string Who() { return "auditor"; }
}

string Trace(IAudited a) { return a.Who(); }
```

## See also       {#see-also}
- [Class inheritance](https://osysharp.com/reference/class/inheritance/) — `class B : A`, `virtual`/`override`/`abstract`, and when a base class is the better shape
- [class methods](https://osysharp.com/reference/class/methods/) — the members an implementation is made of
- [Sequence fields on a class](https://osysharp.com/reference/class/collections/) — holding many implementors in a `List<IContract>`
- [Contracts between kits — an interface in a package, and its version](https://osysharp.com/reference/project/contracts/) — a contract in a PACKAGE: versions, adapters, and what `osy lock` refuses
