Class

On this page 7

A class is a named, reusable definition that specifies the data (state) and the operations (behavior) shared by a family of objects. In object-oriented programming, a class acts as a blueprint and a type at the same time: code creates concrete objects, called instances, from it, and the compiler or runtime uses it to decide which operations those instances support.

Classes are the main unit of design in languages such as Java, C#, C++, Python, Kotlin and Swift. They bundle fields and methods into one cohesive module, control what outside code may touch through encapsulation, and provide the anchor points for inheritance and polymorphism, the neighboring concepts of this topic in programming.

How a class turns into objects

A class becomes useful only when code instantiates it, usually with a new expression or by calling the class like a function, as in Python. The runtime allocates memory for the instance fields, runs a constructor that establishes a valid initial state, and returns a reference to the new object. The class itself is stored once; each object holds only its own field values.

Methods are not copied into every object. An instance method is compiled once and receives the target object as a hidden parameter, named this in Java, C# and C++ and self in Python. When a method is virtual, the call is resolved at run time through a method table (often called a vtable), which is the mechanism behind dynamic dispatch.

The following table lists the members a typical class declaration contains and the role each one plays.

MemberWhat it holds or doesExample in Java
Instance fieldState stored separately in every objectprivate double balance;
Static fieldOne value shared by the whole classstatic int count;
ConstructorInitializes a new object and enforces invariantsAccount(String owner)
Instance methodBehavior that reads or changes the object statevoid deposit(double amount)
Static methodBehavior tied to the class, not to an instancestatic Account open()
Nested typeA helper class scoped inside the outer classstatic class Builder
Typical members of a class

A well-designed class protects its invariants, the conditions that must always hold for its objects, such as a balance that never drops below zero. The constructor establishes the invariant, and every public method must preserve it.

A class differs from an object in the same way a definition differs from a value: there is one Invoice class, but an application may hold thousands of Invoice objects at once. Confusing the two leads to errors such as storing per-object data in a static field, which silently shares it across all instances.

The table below separates the class from the constructs it is most often confused with.

ConstructHolds stateProvides implementationCan be instantiated
ClassYesYesYes
Abstract classYesPartlyNo, only its subclasses
InterfaceNo instance stateUsually no, except default methodsNo
ObjectYes, its own valuesUses the methods of its classIt is already an instance
Struct (C#, Swift)YesYesYes, with value semantics
How a class compares with related constructs

Not every object-oriented language needs classes. JavaScript is prototype-based: objects inherit directly from other objects, and the class keyword introduced in ECMAScript 2015 is largely syntax over prototypes. Python treats classes themselves as objects whose type is a metaclass, which allows classes to be created and modified at run time.

Kinds of classes and member visibility

Languages offer several class variants, each fitting a different design need. Choosing the right kind communicates design intent to other developers and lets the compiler enforce it.

VariantDefining traitTypical use
Concrete classFully implemented and instantiableDomain entities, services
Abstract classDeclares abstract methods for subclassesShared base with partial logic
Final or sealed classCannot be subclassed, or only by listed typesSecurity-sensitive or closed hierarchies
Record or data classCompiler generates equality, hashing and accessorsImmutable value carriers, DTOs
Generic classParameterized by one or more typesTyped collections and containers
Inner or anonymous classDefined inside another class or expressionCallbacks, iterators, small adapters
Common class variants and when each applies

Access modifiers decide which code may use each member and are the primary tool of encapsulation. The exact keywords vary: Java and C# use public, protected and private, Java adds package-private as its default, and Python relies on a naming convention with a leading underscore rather than enforced rules. A sound default is to make fields private and expose only the methods that callers genuinely need.

Designing a cohesive class

A good class has one clear responsibility and a name that states it, usually a noun such as PaymentGateway or ShoppingCart. This idea is captured by the single responsibility principle, the first of the SOLID principles: a class should have only one reason to change.

  • Prefer composition over inheritance: hold a reference to a helper object instead of extending a base class only to reuse its code.
  • Keep the public surface small, because every public method becomes a commitment that later changes can break.
  • Make value-like classes immutable, so instances can be shared across threads without locks.
  • Validate in the constructor, so an invalid object can never exist.
  • Depend on interfaces, not on concrete classes, to keep units testable and replaceable.

Size is a useful warning signal. Opinions differ, but a class that grows beyond a few hundred lines or dozens of methods usually mixes responsibilities and benefits from being split.

Common class design mistakes

Most problems with classes come from poor boundaries rather than from syntax. The table maps frequent symptoms to their causes and the usual remedy.

SymptomLikely causeRemedy
God class with thousands of linesToo many responsibilities in one placeExtract cohesive classes
Anemic model with only getters and settersBehavior lives in separate service classesMove logic next to its data
Fragile subclasses after a base changeDeep inheritance used for code reuseReplace with composition
Objects in an invalid statePublic setters bypass validationValidate in constructors and methods
Data leaking between instancesPer-object state kept in static fieldsUse instance fields
Class design problems, causes and fixes

Another frequent error is overriding equality without hashing. In Java and C#, a class that overrides equals but not hashCode (or Equals without GetHashCode) breaks hash-based collections, because equal objects may land in different buckets.

In everyday language

A class is like the architectural plan for a house. The plan states how many rooms there are, where the doors go and what each switch does, but nobody can live in a plan. Builders use it to construct real houses, and every house built from the same plan has the same layout while holding different furniture and different residents.

In software, the class is the plan and the objects are the houses. One class can produce many objects, each with its own data but all following the same rules.

Seen in the real world

A development team building an online bookstore models its checkout with a ShoppingCart class. The class holds a private list of line items and exposes methods such as addItem, removeItem and total. The constructor creates an empty cart, and addItem rejects a quantity of zero or less, so no cart can ever contain an invalid line.

On a busy afternoon the server holds about 4,000 carts in memory at once. All of them are instances of the same class: the method code exists once, while each object stores only its own items. When the team later adds a 10% discount rule for orders above 50 dollars, they change a single method in one class, and every cart in the system follows the new rule after deployment.