# override (a narrower reference)

> On a subtype, `override Company Organization;` narrows a reference the base declares to a type derived from the base's: the same member and the same column, typed narrower, so code holding the subtype reaches the narrower type's fields. A write that is not the narrower type is refused.

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

## Summary        {#summary}
A subtype may **narrow a reference it inherits**: `override Company Organization;` on `CompanyMember : Membership`
says that every `CompanyMember`'s `Organization` is a `Company`, where `Membership` only promised an `Org`. It is
C#'s covariant override applied to a stored reference — the **same member and the same column**, typed narrower on
the subtype and on every type below it. So `m.Organization.Slug` compiles when `m` is a `CompanyMember`, in a
function, in LINQ and in a policy, with no `is` test at each use.

## Signature      {#signature}
```osy syntax
entity <Subtype> : <Base> {
  override <NarrowerType> <Member>;   // <Member> is a reference <Base> declares; <NarrowerType> derives from its type
}
```

## Description    {#description}

### When do I need it?                              {#when}
When you derive from a base whose references point at another base — most often a package's: a kit's `Membership`
holds the kit's `Organization`, and your app derives its own `Organization : Osysharp.Organizations.Organization` with
the fields it keeps. Without the override, every member's organization is typed as the kit's, and reaching your field
means a test at each use (`if (m.Organization is Organization o) …`). With it, the subtype says once what it holds.

### What does it change, and what does it keep?    {#what}
It changes the member's **type** on this subtype and below it. Everything else is the base's, because the column is:

- **No new column.** The member stays the base's one column in the base's table; nothing in the database changes.
- **The base's attributes, default and nullability stand.** An override names a type and nothing else, so
  `[Required] override …`, `override Company Organization = …;` and a computed `=> …` are refused by name.
- **Code holding the base still sees the base's type.** A `Membership` variable that happens to hold a `CompanyMember`
  reads `Organization` as an `Org`, as in C#.
- **A type below the subtype inherits the narrowing**, and may narrow it again to something derived further.

### Which types may it name?                       {#rules}
The override's type must be the base member's type or **derive from it**: narrowing promises every reader holding
the subtype a row of the kind the base already promised. Refused, each with its own message:

| you wrote | refused because |
|---|---|
| `override Team Organization;` where `Team` does not derive from `Org` | not narrower — the message lists every type here that derives from `Org` |
| `override string Note;` | only a reference to an entity can be narrowed |
| `override Company[] Organizations;` over a collection | only a single reference: a collection is a view over another table, not a column |
| `override Company Nothing;` with no `Nothing` above | nothing to narrow — check the spelling |
| `Company Organization;` without `override` | a second declaration of one column; the message suggests `override` |

### What happens on a write?                       {#writes}
The column must hold only the narrower type, so reads through the subtype are sound:

- **Where the compiler knows the value's type**, assigning a wider one is a compile error —
  `m.Organization = org;` with `org` an `Org` is refused, and the message names the `is` test that makes it legal.
- **Where it cannot** — a write through the base's type (`Membership b = m; b.Organization = org;`), or a bare id
  arriving from an import or the API — the write is refused when it is made, as a `ValidationException` that names
  both types. A row of the narrower type is written through the same handle as usual.

### Two subtypes, two narrowings                     {#siblings}
Siblings may narrow the same member to different types — `CompanyMember` to `Company`, `TeamMember` to `Team`. They
are still the base's one column; each subtype holds only its own kind.

## Examples       {#examples}

```osy title="a membership whose organization is a company" test app=entity-override
entity Org {
  [Required, MaxLength(200)] string Name;
}

entity Company : Org {
  [MaxLength(40)] string Slug = "";
}

entity Membership {
  [Required] Org Organization;
  [MaxLength(200)] string Email = "";
}

// The same column, typed narrower: every CompanyMember's Organization is a Company.
entity CompanyMember : Membership {
  override Company Organization;
}

// No `is` test: the member is a Company wherever a CompanyMember holds it — in memory and in a query.
string SlugOf(CompanyMember m) { return m.Organization.Slug; }
int AtAcme() { return CompanyMember.Count(m => m.Organization.Slug == "acme"); }
```

## See also       {#see-also}
- [entity Sub : Base](https://osysharp.com/reference/entity/inheritance/) — what a subtype shares with its base, and why a redeclared member is one column
- [relations](https://osysharp.com/reference/entity/relations/) — references, and a reference typed as a base holding any of its subtypes
- [sealed](https://osysharp.com/reference/entity/sealed/) — how a type says no one may derive from it
