Osy#the first language built for agents
Agents firstAgentic appsWorkflowsDurable Execution — built inSecurityTestingThe editorThe UI modelOne program

Reference / Class

class methods

class <Name> { public <Type> <Field>; public <Return> <Method>(<params>) { … } }

Behaviour attached to a class — a method with a receiver, called as value.Method(). Classes are in-memory values, so a method is the natural place for logic that belongs to a shape rather than to the database.

stable3 examples compiled by CIclasslogic

Summary#

A class may declare methods, called on a value: cart.Total(). A method has a receiver — the instance it was called on — and can read and write that instance's fields.

Use a method when the logic belongs to the shape. Use a function when it belongs to the application.

Signature#

class <Name> {
  public <Type> <Field>;
  public <Return> <Method>(<params>) { … }   // reads/writes this instance's fields
}

Description#

A method reads its own fields#

Inside a method the class's fields are in scope by name — there is no ceremony:

class Line {
  public string Sku;
  public int Qty;
  public decimal UnitPrice;

  public decimal Total() {
    return Qty * UnitPrice;
  }
}

decimal LineTotal(string sku, int qty, decimal price) {
  var line = new Line { Sku = sku, Qty = qty, UnitPrice = price };
  return line.Total();
}

A method can mutate the instance#

A class is an in-memory value, so a method may change it. Nothing is persisted — there is no row behind it:

class Basket {
  public decimal Total;
  public int Count;

  public void Add(decimal amount) {
    Total = Total + amount;
    Count = Count + 1;
  }

  public decimal Average() {
    return Count == 0 ? 0m : Math.Round(Total / Count, 2);
  }
}

decimal AverageOfThree(decimal a, decimal b, decimal c) {
  var basket = new Basket { };
  basket.Add(a);
  basket.Add(b);
  basket.Add(c);
  return basket.Average();
}

Can a component hold one as state?#

A component field can hold a class instance, and its methods are callable from the component's actions and lifecycle hooks like any other value. This is how a small piece of behaviour — a gate, a counter, a tiny state machine — lives beside the page that uses it rather than being spread across loose fields.

The worked example is a cooldown: "don't do this again until N has passed", which has no cadence of its own and so is not what on every is for.

class Cooldown {
  public DateTime ReadyAt;

  /// True once the wait has passed — then `Arm` starts the next one.
  public bool Ready() { return DateTime.UtcNow >= ReadyAt; }
  public void Arm(TimeSpan wait) { ReadyAt = DateTime.UtcNow + wait; }
}

[Page("/cooldown")]
[AllowAnonymous]
component Repeater() {
  // Ready immediately — a field is required by default, so it is given a value at the create site.
  Cooldown gate = new Cooldown { ReadyAt = DateTime.UtcNow };
  int fired = 0;

  action Nudge() {
    // Held down, this fires at most once every 90ms rather than once per event.
    if (gate.Ready()) {
      fired = fired + 1;
      gate.Arm(TimeSpan.FromMilliseconds(90));
    }
  }

  render {
    Stack(gap: 2) {
      Text($"fired {fired}");
      Pressable("nudge", onClick: Nudge);
    }
  }
}

Reading a field (gate.ReadyAt), assigning one (gate.ReadyAt = …) and calling a method (gate.Ready()) all work on such a field. The instance is ordinary component state: it lives as long as the component does, and it is not persisted.

Method or function?#

class methodtop-level function
Has a receiveryes — the instance it is called onno
Called asvalue.Method()Method(value)
Can write rowsno — a class has no tableyes
Good forlogic that belongs to a shapelogic that belongs to the app

An entity cannot have methods: an entity body holds data, and the behaviour that acts on it is a top-level function. That split is deliberate — it keeps the thing that is persisted separate from the thing that is merely computed.

See also#

  • Method overloads — declaring several methods with one name, and how a call picks between them
  • on everyon every, for behaviour that repeats on a clock rather than waiting to be asked
  • constructor — building an instance with arguments
  • function — behaviour that belongs to the application, not to a shape
  • entity — why an entity has no methods

Related

constructor

A class declares one constructor — its name is the class name, it takes no return type, and it runs when you write new…

function

A function is a top-level unit of work, written like a C# method — a return type, a name, typed parameters, a body. It…

entity

Declares a persisted type — a table of rows the app stores, queries and secures. Every entity gets an Id and audit…

JsonSerializer

Turn a value into a JSON string and a JSON string into a typed object — the C#-faithful System.Text.Json spelling…

Method overloads

A class can declare several methods with the same name, as long as they differ in their parameter types. Each call…