# Interfaces — a contract several types can satisfy

> An `interface` declares what a type must do without saying how — methods and property contracts, no bodies and no state. A class may implement several of them 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 bodies and no state.

```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
}

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 — 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) | no | 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.

### 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.
- **Its members take no body.** Behaviour shared between implementors belongs on an abstract class.
- **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>`
