# internal — a member only its own package may call

> A function, a class member or a contract member declared internal is callable only from the package that declares it. Any package may implement a contract's internal member; only the contract's package calls it. An app or another kit that calls it is refused at compile time, by the member's name and the package's.

<!-- id: project-internal-members · area: project · stability: stable · html: https://osysharp.com/reference/project/internal-members/ -->

## Summary        {#summary}

`internal` on a function or a member means **only the package that declares it may call it**. The app's own source
counts as one package; each kit is another.

It is what lets a kit stand *in front of* something. A kit that meters calls to a provider declares the provider's
contract with an internal member: other kits **implement** it, and only the metering kit **calls** it — so every call
goes through the kit's own public function, which records it. A payment provider behind a ledger and a mail carrier
behind an outbox are the same shape.

```osy title="a contract only its own package calls, and the function that stands in front of it" test app=project-internal-members
/// Something that answers a prompt. Any package may implement it; only this one calls `Complete`.
public interface IProvider {
  string Key { get; }
  internal string Complete(string prompt);
}

/// This package's own write: who answered, and how much.
internal string Record(string key, int units) { return key + ":" + units; }

/// The one public way to a provider — it records every call it makes.
public string Ask(IProvider provider, string prompt) {
  var answer = provider.Complete(prompt);
  return Record(provider.Key, answer.Length) + "|" + answer;
}

/// A provider answers the internal member with an internal member of its own.
public class EchoProvider : IProvider {
  public string Key => "echo";
  internal string Complete(string prompt) => "echo " + prompt;
}

string Try() { return Ask(new EchoProvider(), "hi"); }   // "echo:7|echo hi"
```

## Signature      {#signature}

```osy syntax
// package Acme.Meter
public interface IProvider { internal string Complete(string prompt); }   // implemented anywhere, called only here
internal string Record(string key, int units) { … }                       // called only here
public string Ask(IProvider provider, string prompt) { … }                // what everyone else calls

// package Acme.Fast          (use Acme.Meter@0;)
public class FastProvider : IProvider { internal string Complete(string prompt) { … } }
```

## Description    {#description}

### Who may call it?    {#who}

Code written in the **same package** as the declaration — whichever of the package's namespaces it is in, as C#'s
`internal` is the assembly. A package is the unit `package.osy` declares; an app's own source is one too, so inside
an app `internal` does not separate one namespace from another.

| Calling from | An `internal` member of a kit |
|---|---|
| the kit's own source, in any of its namespaces | callable |
| the app that uses the kit | refused |
| another kit, including one that implements the kit's contract | refused |
| a kit or an app that writes the kit's `namespace …;` line | refused — a namespace is a line anyone may write; the package is not |

The refusal names the member and the package:

```console
'Acme.Meter.IProvider.Complete' is internal to the package `Acme.Meter` — it is only callable from code in that package.
`Record` is `internal` to the package `Acme.Meter` — only code in that package may call it, so it is not part of what
that code offers. Only its `public` declarations are reachable from here.
```

### How does another package implement an internal contract member?    {#implementing}

By declaring the member `internal` itself. The contract's package still reaches it, through the contract; the
implementing package may call its own member; nobody else can.

```osy syntax
public class FastProvider : IProvider {
  public string Key => "fast";
  internal string Complete(string prompt) { … }     // not `public`
}
```

Declared `public`, the implementation would be callable by everyone holding a `FastProvider` — around the package the
contract belongs to — so it is refused where it is written. An `override` of an internal method stays internal for the
same reason.

```console
'Acme.Fast.FastProvider.Complete' answers 'Acme.Meter.IProvider.Complete', which is `internal` — only the package that
declares 'Acme.Meter.IProvider' may call it. Declared `public` here, it would be callable around that package. Write
`internal` on 'Acme.Fast.FastProvider.Complete' too: …
```

### Is there another way to reach it?    {#routes}

No. The rule is applied where a call is built, so the spelling does not matter:

- the qualified name (`Acme.Meter.Record(…)`), the function as a value (`Func<…> f = Record;`), a lambda, a page's
  action;
- a subclass written in another package (`class Mine : FastProvider { … Complete(…) … }`, `base.Complete(…)`) — an
  inherited internal member is still its declarer's;
- a test: `Record.Stub(…)` replaces the function for everything that calls it, so an internal function is no more
  another package's to stub than to call. A kit's test app tests the kit through its public functions.

Two names are refused for the same reason:

- a function whose name begins with two underscores (`__Anything`) — those names are the compiler's own, and it
  trusts some of them by name;
- an app source file under `Capabilities/` or `Core/` — that is where the compiler places the files of the packages
  an app uses, and a file there would be read as that package's code. An app's source lives anywhere else.

### What does the kit's surface show?    {#surface}

`osy kits <Kit> --surface` lists a contract's internal member as `internal` — a class answers it, nobody outside the
kit calls it — and does not list an internal function at all:

```console
contract  IProvider   interface IProvider { internal Complete, Key }
```

For versions, an internal contract member is still something every implementor owes: adding one without a default is
a major version ([Contracts between kits — an interface in a package, and its version](https://osysharp.com/reference/project/contracts/)). It is never part of what a caller can name.

## See also       {#see-also}
- [Contracts between kits — an interface in a package, and its version](https://osysharp.com/reference/project/contracts/) — a contract between kits, and which changes to it need a major version
- [type visibility (public / internal)](https://osysharp.com/reference/types/visibility/) — `public` and `internal` on a type, and the defaults
- [Interfaces — a contract several types can satisfy](https://osysharp.com/reference/class/interfaces/) — interfaces and default members
- [class methods](https://osysharp.com/reference/class/methods/) — member visibility on a class
- [package.osy](https://osysharp.com/reference/project/package/) — `package.osy`: what a package is
