Beginner12 min readObject-Oriented Foundationslive prototype

Classes & Objects

A class is the blueprint; objects are the real things you build from it. Master this and the rest of OOP clicks into place.

The idea

What it is

Almost everything in object-oriented design starts here. A class is a blueprint — it describes what something is and what it can do, but it isn't a real thing yet. An object is a concrete thing built from that blueprint, living in memory with its own data.

Think of a cookie cutter and cookies. The cutter (the class) defines the shape once. Every cookie (an object) is stamped from it — same shape, but each is its own cookie you can decorate differently. You design the cutter one time and stamp out as many cookies as you need.

The one sentence to remember

A class is written once, by you, at design time. Objects are created many times, while the program runs. One blueprint, many instances.

Mechanics

How it works

What's inside a class

A class bundles two things that belong together — data and the behavior that acts on that data:

  • Fields (also called attributes or properties) — the data each object carries. For a Car: its color, brand, and current speed.
  • Methods — the actions an object can perform. For a Car: accelerate(), brake(), describe(). Methods usually read or change the object's own fields.

The constructor: how an object is born

When you write new Car("red", "Tesla"), a special method called the constructor runs. Its job is to set up a brand-new object — taking the values you pass in and storing them in the new object's fields, so it starts life in a valid state.

car.ts
class Car {
  // fields — every car gets its own copy of these
  color: string;
  brand: string;
  speed: number;

  // constructor — runs once, when the object is created
  constructor(color: string, brand: string) {
    this.color = color;
    this.brand = brand;
    this.speed = 0; // every new car starts parked
  }

  // methods — defined once, shared by every car
  accelerate(amount: number) {
    this.speed += amount;
  }

  brake() {
    this.speed = 0;
  }
}

const a = new Car("red", "Tesla");
const b = new Car("blue", "Toyota");
a.accelerate(30); // only 'a' speeds up → a.speed = 30, b.speed = 0

Each object has its own state

This is the part beginners miss. a and b are both cars, but they're separate objects. Changing a does nothing to b. Each object keeps its own private copy of the fields — its own state. That independence is exactly why objects are so useful for modeling many real-world things at once.

The word `this`

Inside a method, this means the specific object the method was called on. When you write a.accelerate(30), inside accelerate the word this refers to a. Call b.accelerate(5) and now this is b. One method definition, but it always acts on whichever object you called it on.

Instance vs. static — a quick peek

Fields like speed belong to each object (instance state). Sometimes you want data shared across all objects of a class — like a running count of how many cars exist. That's a static member, and it lives on the class itself, not on any one object. The prototype tracks Car.totalBuilt to show this.

Interactive prototype

See it. Build it. Break it.

A sandboxed, hands-on simulation — no setup, no install. Play with it as you read.

About this simulation

On the left is the Car class — one blueprint. Press Build a car to stamp out objects from it. Each car you create gets its own color and speed, but they all share the same methods. Hit accelerate on one and watch only that car move — that's independent object state.

Hands-on

Try these yourself

Open the prototype above, predict what happens, then verify.

try 01

One blueprint, many cars

Press Build a car a few times. Notice you wrote the class only once, yet each press produces a brand-new object with its own color. That's the blueprint-to-instance relationship in action.

try 02

Prove state is independent

Build two cars. Click accelerate on the first one only. Watch its speed climb while the second car stays at 0. Changing one object never touches the other — each holds its own state.

try 03

Static vs instance

Keep an eye on Car.totalBuilt at the top of the class card. It goes up every time any car is created, because it lives on the class — not on a single object. Compare that to speed, which is per-car.

In practice

When to use it — and what trips people up

When to model something as a class

  • When you have a thing with data and behavior that belong together — a User, an Order, a Car, a Game.
  • When you'll have many of that thing, each with its own state — thousands of users, hundreds of orders.
  • When you want to hide the details and expose a clean set of actions (methods) instead of letting outside code poke at raw fields.

Don't over-class everything

Not every bit of code needs a class. A pure calculation with no state is often just a function. Reach for a class when there's state to hold and behavior that belongs with it — that's the sweet spot.

What it gives you

  • Bundles data with the behavior that uses it — related code lives in one place.
  • One blueprint produces unlimited objects, each with independent state.
  • Methods give you a clean, named interface instead of scattered raw data access.
  • It's the foundation every other OOP idea (inheritance, polymorphism, patterns) builds on.

Common mistakes

  • Confusing the class with the object — the blueprint is not the cookie.
  • Forgetting each object has its own state, and accidentally sharing data that should be per-object.
  • Putting everything in the constructor, or letting one class do far too much (a 'God object').
  • Exposing fields directly instead of guarding them behind methods.

Reference

Code & further reading

A minimal reference implementation and pointers worth bookmarking.

// Same idea, a different domain. Pick your language above.
class BankAccount {
  private balance: number;

  constructor(public owner: string, opening: number) {
    this.balance = opening; // each account gets its own balance
  }

  deposit(amount: number) {
    this.balance += amount;
  }

  withdraw(amount: number) {
    if (amount > this.balance) throw new Error("Insufficient funds");
    this.balance -= amount;
  }

  getBalance() {
    return this.balance;
  }
}

const alice = new BankAccount("Alice", 100);
const bob = new BankAccount("Bob", 0);
alice.deposit(50);   // alice → 150
bob.withdraw(10);    // throws — bob's own balance is 0
// alice and bob are independent objects of the same class.

References & further reading

5 sources

Knowledge check

Did it land?

Quick questions, answers revealed on submit. Nothing is scored or saved.

question 01 / 04

Which statement best describes the difference between a class and an object?

question 02 / 04

What does the new keyword do in new Car("red", "Tesla")?

question 03 / 04

You create two cars, a and b, then call a.accelerate(30). What is b.speed?

question 04 / 04

A Car class has a speed field and a Car.totalBuilt counter that increases each time any car is created. Which is which?

0/4 answered