<p>Taking <a href="https://langdev.stackexchange.com/questions/1774/distinguishing-classes-from-structures/">this question</a> to its logical extreme. Some languages like C++ and Python use <code>class</code> for everything. Python classes are classes, interfaces (both nominal and structural), mixins, and namespaces, all rolled into one keyword. Other languages tend to split these things out, using different keywords for different concepts. You see <code>interface</code> crop up a lot, for defining behaviors abstractly without allowing the <code>interface</code> to be directly instantiated. Some languages have others, for instance Raku <code>role</code>s are mixins, and Scala and Kotlin have singleton <code>object</code>s baked in.</p>
<p>What are the different class-like constructs that are seen in programming languages today? What do they do differently, and what motivates each one?</p>

<object-oriented><classes>
What are the different class-like constructs that languages use today?
CC BY-SA 4.0
2023-09-17T22:28:54.060Z
**ML-style modules.** Originally, modules were second-class citizens in ML-family languages. This was done in order to enforce predicativity of module types. Over time, ML-style modules evolved, see e.g. Ocaml modules (now first-class citizens) and Scala's singleton objects.
Martin Berger
<p>Here's my attempt at categorising them. I've tried to cover the most significant differences between these constructs in different languages, and I've tried to choose language-agnostic terms; but those are somewhat subjective considerations, so take it with a grain of salt. This will also necessarily be biased towards constructs in languages I'm familiar with.</p>
<h2>Structs</h2>
<p>Probably the simplest <a href="https://en.wikipedia.org/wiki/Composite_data_type" rel="nofollow noreferrer">composite data type</a>; it consists of a set of fields, each of which has a name and a type. The only things you can do with them are construct them (by providing values for each field), and read or write fields by name. Generally, all field accesses are static, meaning it's known at compile-time which field an access is bound to; you can't do things like <code>my_struct[some_field]</code> where <code>some_field</code> is itself a variable, at least not unless the language supports some kind of <a href="https://en.wikipedia.org/wiki/Reflective_programming" rel="nofollow noreferrer">reflection</a>.</p>
<p>Generally, structs are <a href="https://en.wikipedia.org/wiki/Value_type_and_reference_type" rel="nofollow noreferrer">value types</a>, but languages which support them usually allow taking references to them too; and they are <a href="https://en.wikipedia.org/wiki/Nominal_type_system" rel="nofollow noreferrer">nominal types</a>, so two struct types with the same field names and types aren't compatible.</p>
<p>Structs may have functions associated with them, which might <em>look</em> like methods if the language supports <a href="https://en.wikipedia.org/wiki/Uniform_Function_Call_Syntax" rel="nofollow noreferrer">Uniform Function Call Syntax</a> (UFCS). However, I do not classify them as <a href="https://en.wikipedia.org/wiki/Method_(computer_programming)" rel="nofollow noreferrer">methods</a> since they are not dynamically dispatched based on the subject's runtime type.</p>
<h2>Tuples (product types)</h2>
<p>These are similar to structs: the most obvious difference is that the fields are numbered (or ordered) rather than named. However, there are a few more subtle differences.</p>
<p>Tuple types are almost always value types, and <a href="https://en.wikipedia.org/wiki/Structural_type_system" rel="nofollow noreferrer">structural types</a>, meaning that two tuple types are compatible if their respective component types are. They may also be <a href="https://en.wikipedia.org/wiki/Anonymous_type" rel="nofollow noreferrer">anonymous types</a>. A tuple type may be representable as e.g. <code>S * T</code> or <code>(S, T)</code> where <code>S</code> and <code>T</code> are themselves types; this means that <a href="https://en.wikipedia.org/wiki/Generic_programming" rel="nofollow noreferrer">generic</a> functions can operate on tuples in ways that they would not be able to on structs.</p>
<p>I don't know of any languages besides Rust which allow associated functions and UFCS with tuple types.</p>
<h2>Records</h2>
<p>In many contexts <a href="https://en.wikipedia.org/wiki/Record_(computer_science)" rel="nofollow noreferrer">a record</a> is a synonym for a struct. However, at least to me the term &quot;record&quot; has a few different connotations to term &quot;struct&quot;. For one, records might be comparable for equality (by comparing their fields) by default, and they are normally used for things where such comparison would make sense. If two record instances happened to have equal fields despite not logically being equal (in the <a href="https://en.wikipedia.org/wiki/Domain_(software_engineering)" rel="nofollow noreferrer">domain</a>), then normally the programmer would add an explicit &quot;identity&quot; or &quot;ID&quot; field in order to differentiate them. So records are value types but they are often used to model things which have identities.</p>
<p>Record types might be either nominal or structural. If they are structural, then there is probably a subtyping relationship between records which have strictly more fields, and possibly when the type of a field in one record is a subtype of that field's type in another record.</p>
<h2>Classes</h2>
<p>There are several major distinctions between classes and structs, mostly relating to the fundamental principles of <a href="https://en.wikipedia.org/wiki/Object-oriented_programming" rel="nofollow noreferrer">Object-Oriented Programming</a>. Like structs, they have named fields, and field accesses are (usually) either statically bound, or at least refer to statically-known field names.</p>
<p>The most significant feature of classes is that they can have <a href="https://en.wikipedia.org/wiki/Method_(computer_programming)" rel="nofollow noreferrer">methods</a>. The difference between a function and a method is that a method can be overridden, so there can be multiple implementations of a method, and when the method is invoked, it is <a href="https://en.wikipedia.org/wiki/Dynamic_dispatch" rel="nofollow noreferrer">dynamically dispatched</a> (i.e. an implementation is selected at runtime) based on the subject's runtime type.</p>
<p>Classes also have <a href="https://en.wikipedia.org/wiki/Constructor_(object-oriented_programming)" rel="nofollow noreferrer">constructors</a> or initialisers ─ special methods (or method-like members) which are invoked when the class is instantiated. Whereas structs can be constructed as data by just providing their field values, class constructors might provide their own values for some or all of the class's fields, or perform other behaviour.</p>
<p>Generally, classes are reference types ─ instances with equal fields still have different identities ─ and they are nominal types.* They can be extended by <a href="https://en.wikipedia.org/wiki/Inheritance_(object-oriented_programming)#Subclasses_and_superclasses" rel="nofollow noreferrer">subclasses</a>, which inherit members (fields and methods) from their superclasses. (This could be single or <a href="https://en.wikipedia.org/wiki/Multiple_inheritance" rel="nofollow noreferrer">multiple inheritance</a>.) Class inheritance also implies subtyping: subclasses are subtypes of their superclasses.</p>
<p>Particularly in statically typed languages, there is likely to be some kind of <a href="https://en.wikipedia.org/wiki/Information_hiding" rel="nofollow noreferrer">visibility</a> feature for class members, allowing them to be declared as public or private (or possibly other visibilities).</p>
<p><sub>* I don't know of any languages besides Typescript in which classes are structurally typed. Even in Typescript, structural compatibility of two classes unrelated by inheritance is almost always unintended, and a source of potential bugs.</sub></p>
<h2>Dynamic classes</h2>
<p>These are almost always just called &quot;classes&quot;, but I think it's important to distinguish the classes in languages like Javascript or Python from the classes in languages like Java or C#. Dynamic classes actually exist at runtime and are values in their own right. This is in contrast to e.g. <code>Class&lt;?&gt;</code> instances in Java, which <em>represent</em> the class but are a different language construct distinct from the class itself.</p>
<p>Dynamic classes are usually mutable: they can be <a href="https://en.wikipedia.org/wiki/Monkey_patch" rel="nofollow noreferrer">monkey-patched</a>, changing the behaviour of their instances, often even instances which had already been constructed before the monkey-patch was made. New dynamic classes can be declared at runtime, and they might extend other dynamic classes without necessarily knowing at &quot;compile-time&quot; <em>which</em> other class they extend.</p>
<h2>Mixins</h2>
<p>These are similar to classes, in that they can declare fields and methods, and can inherit members or be inherited from. The difference is that a mixin cannot be constructed directly, and it might not even actually be a type (rather, it is only a blueprint for a set of members).</p>
<p>Mixins may be a separate language construct from classes in order to provide a mechanism for multiple inheritance, if the language only allows single inheritance for classes. In this case, a class can inherit from any number of mixins but may only (directly) extend one other class.</p>
<h2>Dynamic objects</h2>
<p>These are objects, generally in dynamic languages like Javascript or Python, which allow fields to be added or removed, or their types changed, at runtime. All accesses (fields and methods) are dynamically dispatched, since it isn't necessarily possible to know statically whether a particular object will even have a particular member.</p>
<p>They are always reference types. They might support inheritance from a dynamic class or a <a href="https://en.wikipedia.org/wiki/Prototype-based_programming" rel="nofollow noreferrer">prototype</a>, or not at all. In the latter case, they are constructed by directly listing their members. It is often possible to access fields dynamically, e.g. <code>my_object[some_field]</code> where <code>some_field</code> is itself a variable, or to iterate over an object's members, without needing a special API for reflection.</p>
<p>Dynamic objects only exist in dynamically-typed languages, so <a href="https://en.wikipedia.org/wiki/Duck_typing" rel="nofollow noreferrer">duck typing</a> with them is common. Such languages sometimes later introduce an optional static or <a href="https://en.wikipedia.org/wiki/Gradual_typing" rel="nofollow noreferrer">gradual type system</a>, but these are generally not powerful enough to describe every way that dynamic objects are used in practice.</p>
<h2>Interfaces</h2>
<p>An interface is a <a href="https://en.wikipedia.org/wiki/Abstract_data_type" rel="nofollow noreferrer">data type</a> that is not a <a href="https://en.wikipedia.org/wiki/Data_structure" rel="nofollow noreferrer">data structure</a>. Typically it is declared similarly to a class, but <em>all</em> of its members are dynamically dispatched. For example, in a language where class field accesses are statically bound, interfaces probably would not be allowed to declare fields.</p>
<p>Unlike concrete data types which can be instantiated directly, interfaces are <em>implemented</em> by other types (particularly classes), so to get a value of an interface type you must construct a value of some concrete type which implements the interface. Interfaces may be nominally or structurally typed; i.e. the language may or may not require you to declare explicitly which interfaces are implemented by a class.</p>
<p>An interface which declares methods generally does not provide implementations of them; those are instead provided by implementing classes.</p>
<h2>Traits</h2>
<p>These are quite similar to interfaces, in that they are data types but not data structures, they are implemented by other types, and the trait declaration generally doesn't provide implementations for its own members. However, at least to me a &quot;trait&quot; does not necessarily mean that its members must be dynamically dispatched, and this means traits can be implemented by structs or other types which don't have any dynamically dispatched members.</p>
<p>Still, since a trait may be implemented by multiple types, this means that when a trait &quot;method&quot; is invoked, an implementation needs to be selected. This could be either by <a href="https://en.wikipedia.org/wiki/Monomorphization" rel="nofollow noreferrer">monomorphisation</a> of generic functions at compile-time, or by dynamic dispatch at runtime (Rust, for example, supports both).</p>

CC BY-SA 4.0
2023-09-17T11:52:26.360Z
2023-09-20T21:36:53.697Z
2023-09-20T21:36:53.697Z
kaya3
CC BY-SA 4.0
2023-09-18T15:07:43.117Z
This is a comprehensive answer, and I'd like to point out that languages which have classes sometimes also define metaclasses, which are useful to distinguish between "what" is implemented and "how" it is implemented. I however don't know if that makes an answer on its own.
coredump
CC BY-SA 4.0
2023-09-19T10:02:19.547Z
@coredump Fair point; I didn't count metaclasses since I only know of them in Python. Python's metaclasses are really just classes, and it's the "A is the metaclass of B" relationship that distinguishes them. In that sense the language construct is really a relationship between classes rather than an alternative to them. Similarly, Java has inner classes, which are a kind if class and it's the relationship to the outer class that distinguishes them.
kaya3
CC BY-SA 4.0
2023-09-20T21:29:23.480Z
Interfaces are called "abstract classes" in some languages.
Barmar
CC BY-SA 4.0
2023-09-20T21:32:15.887Z
@Barmar In all the languages I'm familiar with, abstract classes are classes which don't necessarily provide implementations for all of their members ─ as opposed to interfaces, which don't (generally) provide implementations for *any* of their members. Which languages are you referring to?
kaya3
CC BY-SA 4.0
2023-09-20T21:39:16.257Z
True. Abstract classes are generally used for all the different class-like things that can't be instantiated by themselves. So interfaces, traits, mixins. Interfaces are abstract classes that don't provide any implementation, just declarations.
Barmar
CC BY-SA 4.0
2023-09-22T18:25:00.960Z
Can you clarify the differences between mixins and traits? (The only relevant language I know well — Scala — has what it calls ‘traits’, but if I understand correctly they seem more similar to mixins as described here.)
gidds
CC BY-SA 4.0
2023-09-22T22:43:10.117Z
@gidds A mixin is a set of member implementations (which can be inherited by a class), whereas a trait is a set of abstract member declarations (which can be implemented by a class or other data structure). So traits are more similar to interfaces than to mixins. But as mentioned at the start, choosing language-agnostic terms requires making some decisions subjectively; for example, PHP's "traits" are really mixins (in this terminology), and from the looks of it Scala's "traits" are really interfaces (in this terminology).
kaya3
CC BY-SA 4.0
2023-10-03T08:50:12.830Z
Note that C++ (at least) has `struct`s that do not conform to your definition -- by your description, C++ `struct`s are actually classes (the difference between `class` and `struct` in C++ is that `struct` members are public by default, whereas `class` is private).
occipita
# What are the different class-like constructs that languages use today?
Posted by: username_0 on 2023-07-06
Taking [this question](https://langdev.stackexchange.com/questions/1774/distinguishing-classes-from-structures/) to its logical extreme. Some languages like C++ and Python use `class` for everything. Python classes are classes, interfaces (both nominal and structural), mixins, and namespaces, all rolled into one keyword. Other languages tend to split these things out, using different keywords for different concepts. You see `interface` crop up a lot, for defining behaviors abstractly without allowing the `interface` to be directly instantiated. Some languages have others, for instance Raku `role`s are mixins, and Scala and Kotlin have singleton `object`s baked in.

What are the different class-like constructs that are seen in programming languages today? What do they do differently, and what motivates each one?
**Tags:** object-oriented classes
> **Comments:**
> **username_1**: **ML-style modules.** Originally, modules were second-class citizens in ML-family languages. This was done in order to enforce predicativity of module types. Over time, ML-style modules evolved, see e.g. Ocaml modules (now first-class citizens) and Scala's singleton objects.  
---
## 1 answers
### Answer by username_2 on 2023-09-17. Score: 9
Here's my attempt at categorising them. I've tried to cover the most significant differences between these constructs in different languages, and I've tried to choose language-agnostic terms; but those are somewhat subjective considerations, so take it with a grain of salt. This will also necessarily be biased towards constructs in languages I'm familiar with.

## Structs

Probably the simplest [composite data type](https://en.wikipedia.org/wiki/Composite_data_type); it consists of a set of fields, each of which has a name and a type. The only things you can do with them are construct them (by providing values for each field), and read or write fields by name. Generally, all field accesses are static, meaning it's known at compile-time which field an access is bound to; you can't do things like `my_struct[some_field]` where `some_field` is itself a variable, at least not unless the language supports some kind of [reflection](https://en.wikipedia.org/wiki/Reflective_programming).

Generally, structs are [value types](https://en.wikipedia.org/wiki/Value_type_and_reference_type), but languages which support them usually allow taking references to them too; and they are [nominal types](https://en.wikipedia.org/wiki/Nominal_type_system), so two struct types with the same field names and types aren't compatible.

Structs may have functions associated with them, which might *look* like methods if the language supports [Uniform Function Call Syntax](https://en.wikipedia.org/wiki/Uniform_Function_Call_Syntax) (UFCS). However, I do not classify them as [methods](https://en.wikipedia.org/wiki/Method_(computer_programming)) since they are not dynamically dispatched based on the subject's runtime type.

## Tuples (product types)

These are similar to structs: the most obvious difference is that the fields are numbered (or ordered) rather than named. However, there are a few more subtle differences.

Tuple types are almost always value types, and [structural types](https://en.wikipedia.org/wiki/Structural_type_system), meaning that two tuple types are compatible if their respective component types are. They may also be [anonymous types](https://en.wikipedia.org/wiki/Anonymous_type). A tuple type may be representable as e.g. `S * T` or `(S, T)` where `S` and `T` are themselves types; this means that [generic](https://en.wikipedia.org/wiki/Generic_programming) functions can operate on tuples in ways that they would not be able to on structs.

I don't know of any languages besides Rust which allow associated functions and UFCS with tuple types.

## Records

In many contexts [a record](https://en.wikipedia.org/wiki/Record_(computer_science)) is a synonym for a struct. However, at least to me the term "record" has a few different connotations to term "struct". For one, records might be comparable for equality (by comparing their fields) by default, and they are normally used for things where such comparison would make sense. If two record instances happened to have equal fields despite not logically being equal (in the [domain](https://en.wikipedia.org/wiki/Domain_(software_engineering))), then normally the programmer would add an explicit "identity" or "ID" field in order to differentiate them. So records are value types but they are often used to model things which have identities.

Record types might be either nominal or structural. If they are structural, then there is probably a subtyping relationship between records which have strictly more fields, and possibly when the type of a field in one record is a subtype of that field's type in another record.

## Classes

There are several major distinctions between classes and structs, mostly relating to the fundamental principles of [Object-Oriented Programming](https://en.wikipedia.org/wiki/Object-oriented_programming). Like structs, they have named fields, and field accesses are (usually) either statically bound, or at least refer to statically-known field names.

The most significant feature of classes is that they can have [methods](https://en.wikipedia.org/wiki/Method_(computer_programming)). The difference between a function and a method is that a method can be overridden, so there can be multiple implementations of a method, and when the method is invoked, it is [dynamically dispatched](https://en.wikipedia.org/wiki/Dynamic_dispatch) (i.e. an implementation is selected at runtime) based on the subject's runtime type.

Classes also have [constructors](https://en.wikipedia.org/wiki/Constructor_(object-oriented_programming)) or initialisers ─ special methods (or method-like members) which are invoked when the class is instantiated. Whereas structs can be constructed as data by just providing their field values, class constructors might provide their own values for some or all of the class's fields, or perform other behaviour.

Generally, classes are reference types ─ instances with equal fields still have different identities ─ and they are nominal types.\* They can be extended by [subclasses](https://en.wikipedia.org/wiki/Inheritance_(object-oriented_programming)#Subclasses_and_superclasses), which inherit members (fields and methods) from their superclasses. (This could be single or [multiple inheritance](https://en.wikipedia.org/wiki/Multiple_inheritance).) Class inheritance also implies subtyping: subclasses are subtypes of their superclasses.

Particularly in statically typed languages, there is likely to be some kind of [visibility](https://en.wikipedia.org/wiki/Information_hiding) feature for class members, allowing them to be declared as public or private (or possibly other visibilities).

\* I don't know of any languages besides Typescript in which classes are structurally typed. Even in Typescript, structural compatibility of two classes unrelated by inheritance is almost always unintended, and a source of potential bugs.

## Dynamic classes

These are almost always just called "classes", but I think it's important to distinguish the classes in languages like Javascript or Python from the classes in languages like Java or C#. Dynamic classes actually exist at runtime and are values in their own right. This is in contrast to e.g. `Class`  instances in Java, which *represent* the class but are a different language construct distinct from the class itself.

Dynamic classes are usually mutable: they can be [monkey-patched](https://en.wikipedia.org/wiki/Monkey_patch), changing the behaviour of their instances, often even instances which had already been constructed before the monkey-patch was made. New dynamic classes can be declared at runtime, and they might extend other dynamic classes without necessarily knowing at "compile-time" *which* other class they extend.

## Mixins

These are similar to classes, in that they can declare fields and methods, and can inherit members or be inherited from. The difference is that a mixin cannot be constructed directly, and it might not even actually be a type (rather, it is only a blueprint for a set of members).

Mixins may be a separate language construct from classes in order to provide a mechanism for multiple inheritance, if the language only allows single inheritance for classes. In this case, a class can inherit from any number of mixins but may only (directly) extend one other class.

## Dynamic objects

These are objects, generally in dynamic languages like Javascript or Python, which allow fields to be added or removed, or their types changed, at runtime. All accesses (fields and methods) are dynamically dispatched, since it isn't necessarily possible to know statically whether a particular object will even have a particular member.

They are always reference types. They might support inheritance from a dynamic class or a [prototype](https://en.wikipedia.org/wiki/Prototype-based_programming), or not at all. In the latter case, they are constructed by directly listing their members. It is often possible to access fields dynamically, e.g. `my_object[some_field]` where `some_field` is itself a variable, or to iterate over an object's members, without needing a special API for reflection.

Dynamic objects only exist in dynamically-typed languages, so [duck typing](https://en.wikipedia.org/wiki/Duck_typing) with them is common. Such languages sometimes later introduce an optional static or [gradual type system](https://en.wikipedia.org/wiki/Gradual_typing), but these are generally not powerful enough to describe every way that dynamic objects are used in practice.

## Interfaces

An interface is a [data type](https://en.wikipedia.org/wiki/Abstract_data_type) that is not a [data structure](https://en.wikipedia.org/wiki/Data_structure). Typically it is declared similarly to a class, but *all* of its members are dynamically dispatched. For example, in a language where class field accesses are statically bound, interfaces probably would not be allowed to declare fields.

Unlike concrete data types which can be instantiated directly, interfaces are *implemented* by other types (particularly classes), so to get a value of an interface type you must construct a value of some concrete type which implements the interface. Interfaces may be nominally or structurally typed; i.e. the language may or may not require you to declare explicitly which interfaces are implemented by a class.

An interface which declares methods generally does not provide implementations of them; those are instead provided by implementing classes.

## Traits

These are quite similar to interfaces, in that they are data types but not data structures, they are implemented by other types, and the trait declaration generally doesn't provide implementations for its own members. However, at least to me a "trait" does not necessarily mean that its members must be dynamically dispatched, and this means traits can be implemented by structs or other types which don't have any dynamically dispatched members.

Still, since a trait may be implemented by multiple types, this means that when a trait "method" is invoked, an implementation needs to be selected. This could be either by [monomorphisation](https://en.wikipedia.org/wiki/Monomorphization) of generic functions at compile-time, or by dynamic dispatch at runtime (Rust, for example, supports both).
> **Comments:**
> **username_3** (2023-09-18): This is a comprehensive answer, and I'd like to point out that languages which have classes sometimes also define metaclasses, which are useful to distinguish between "what" is implemented and "how" it is implemented. I however don't know if that makes an answer on its own.  
> **username_2** (2023-09-19): @coredump Fair point; I didn't count metaclasses since I only know of them in Python. Python's metaclasses are really just classes, and it's the "A is the metaclass of B" relationship that distinguishes them. In that sense the language construct is really a relationship between classes rather than an alternative to them. Similarly, Java has inner classes, which are a kind if class and it's the relationship to the outer class that distinguishes them.  
> **username_4** (2023-09-20): Interfaces are called "abstract classes" in some languages.  
> **username_2** (2023-09-20): @Barmar In all the languages I'm familiar with, abstract classes are classes which don't necessarily provide implementations for all of their members ─ as opposed to interfaces, which don't (generally) provide implementations for *any* of their members. Which languages are you referring to?  
> **username_4** (2023-09-20): True. Abstract classes are generally used for all the different class-like things that can't be instantiated by themselves. So interfaces, traits, mixins. Interfaces are abstract classes that don't provide any implementation, just declarations.  
> **username_5** (2023-09-22): Can you clarify the differences between mixins and traits? (The only relevant language I know well — Scala — has what it calls ‘traits’, but if I understand correctly they seem more similar to mixins as described here.)  
> **username_2** (2023-09-22): @gidds A mixin is a set of member implementations (which can be inherited by a class), whereas a trait is a set of abstract member declarations (which can be implemented by a class or other data structure). So traits are more similar to interfaces than to mixins. But as mentioned at the start, choosing language-agnostic terms requires making some decisions subjectively; for example, PHP's "traits" are really mixins (in this terminology), and from the looks of it Scala's "traits" are really interfaces (in this terminology).  
> **username_6** (2023-10-03): Note that C++ (at least) has `struct`s that do not conform to your definition -- by your description, C++ `struct`s are actually classes (the difference between `class` and `struct` in C++ is that `struct` members are public by default, whereas `class` is private).  
---
