Simple to grasp explanation of Class v Struct

Could I simply surmise that a Struct was like a forgery; in that it didn't keep it's original value ?

A simple (but slightly inaccurate) way to think about it is that structs have value semantics and classes have reference semantics.

Consider something like:

struct P {
  var x: Int = 0
  var y: Int = 0

  init(x: Int, y: Int) {
    self.x = x
    self.y = y
  }
}

let p = P(x: 0, y: 1)
var q = p
q.x = 1
print("p: \(p.x),\(p.y) q: \(q.x),\(q.y)")

When P is a struct, you get

p: 0,1 q: 1,1

When P is a class (the code is the same, just change struct to class), however, you get

p: 1,1 q: 1,1

If you're familiar with languages with pointers, reference semantics means that when you manipulate class-typed variables, it is like you are manipulating a pointer to a struct, instead of the struct itself.

This is something of a gross oversimplification, but hopefully that helps.

Your friend sits down with a glass of water.
You say β€œI need a drink of water”.

Class: your friend slides the glass over to you.

Struct: your friend gets up and pours you your own glass of water, in the same shaped cup, to the same level.

7 Likes

This is hands down the best explanation of structs vs classes I've ever seen.

1 Like

An alternative way to express this idea is that classes have identity, and structs do not. To extend @Hacksaw's analogy, if your glasses of water are classes then your friend can say "I need that drink of water". If your glasses of water are structs, your friend can only want a drink of water: all equivalent drinks of water are indistinguishable and entirely substitutable.

2 Likes

Of course, though, if glasses of water were classes, we still would have the ability to get another glass of water and copy all the molecules of water from one glass to another and get an indistinguishable and substitutable copy of the glass of water, but that is truly stretching the physical analogy to its limits. :slight_smile:

From an information perspective:

The only information in an instance of a struct are the values of its fields (instance properties). If you copy all of the fields of a struct, the result is indistinguishable from the original.

Instances of classes also have fields, but they also have an additional piece of information - an identifier, unique for every instance, set at creation and stable for the life of the instance. The fields of the class instance are accessed via that identifier. If you copy all of the fields of a class, the result can still be distinguished from the original because the new instance must also have a different identifier.

It's hard to know exactly what you mean by this, but structs are all about their values. Copies of a struct in some way preserve more of their original value than copies of class instances, as they have no additional unique identifiers beyond their field values.

2 Likes

I don't think so, because the duplicated glass of water would still have a different identifier. The difference is important - classes with identical values for their fields (or glasses of water with literally identical molecular structure) are still distinguishable.

In practice, in a computer system, the identifiers are often memory locations because it's convenient, and sometimes they get reused due to the way the system is implemented, but that is a coincidence/random accident. Unless you have a separate system for assigning IDs (e.g. a specialised allocator), every act of creation results in an instance with a semantically new identifier, so it would not possible to perfectly destroy and recreate/duplicate a class instance.

Likewise for structs, if I understand you correctly.

(I know that Swift packs some extra information alongside classes for runtime purposes which of course privilege classes over structs, but have elided them for pedagogical reasons.)

No, structs are defined by the values of their fields. Any other information you can ascertain about them (such as the address of a particular instance) is entirely meaningless. For classes, the address/identifier is actually meaningful, so they are defined by more than just the values of their fields.

It has nothing to do with class metadata. Swift also generates metadata for structs (else you couldn't use reflection to inspect their fields).

I think what you're trying to tell me is about ObjectIdentifier.

@Karl would be right regardless of whether ObjectIdentifier existed. The mere fact that === exists is sufficient to indicate the existence of some identifier of an object that can uniquely distinguish it from another one, even when all their data bits are identical.

Structs with identical values for all their fields are indistinguishable within the language, classes are not.

2 Likes
Terms of Service

Privacy Policy

Cookie Policy