Struct vs Class


swift

Struct vs Class


Daniel Shin - May 17, 2015

This post is about two types in Swift, struct and class.

I won’t be covering any obvious points about them. You can refer to excellent swift doc here.

Though, what I will cover is the nuanced difference between the two and when should you use each.

First, struct

struct derives from word structure in that struct gives a structure to a set of values. It is a container. A container’s identity is frivolous. What matters is what this container contains.

This is an important note. What gives meaning to struct is its values, not the struct itself. It simply exists to contain those values in a more structured way, no more, no less.

class is an enhanced version of struct. class is an Object-Oriented concept and class is what makes of an object. Unlike struct, class’s identity actually matters because it is an ‘object’, not just a container of values.

Sure, object can and do contain values but those values only serve to complement, represent the identity of the given class. Those values mean nothing without the context of the given class. This is unlike struct where each value contained in struct are values that are still meaningful even outside the context of given struct.

Grasping these nuanced differences properly will help branching out to their use cases.

Okay, so enough with the terminologies. Let’s zoom straight down into our focus here, Swift.

In Swift, struct and class are different in a few ways but most distinct of all is the way the two are passed around.

struct is passed by values while class is passed by references. This distinction rhymes well with our understanding about struct and class.

struct is a simple container with values in it so it would be quite stupid to be implemented with passed by reference considering all the overheads associated with keeping references, concurrency issues etc.

class is a representation of an object and therefore, it makes sense to be implemented with passed by reference since the Identity of the class actually matters.

Let me give you an example.

Think struct as something like 3D coordinate. You need X, Y, Z values and it will be less organized and therefore more cumbersome to maintain if you were to keep all the values not contained. This is perfect use case for struct.

Declaration of 3D Coordinate itself doesn’t mean anything significant. What matters is the X, Y, Z values that are contained within.

Think class as an object in real life (as that really is the gist of Object-Oriented Programming). Let’s say cat. class cat is an abstracted representation of all the objects that look, behave etc like cat. And its identity matters.

Tom’s cat and Jessica’s cat are clearly two different objects and you should treat in such a way. This is why class instances are implemented with passed by reference. Whether Tom’s cat is in California or Siberia, it still is Tom’s cat and its identity doesn’t & shouldn’t change. Thus, we keep our reference to that cat wherever it goes (i.e. wherever that class instance is passed to).

Another noticeable distinction has to do with initializer.

struct gets default initializer if no custom initializer is defined while class gets one only if one has no properties defined (or more like properties that need to be populated).

struct 3DCoordinate {
  let x: Int
  let y: Int
  let z: Int
}

With the above setting, you get default initializer for it, which is,

let coord = 3DCoordinate(x: 10, y: 10, z: 10)

In class, you don’t.

This difference in implementation also stems from the conceptual difference that we’ve expounded previously.

struct exists to contain values. Thus, it makes sense to get default initializer to pass those values.

class exists to more than just contain values. You might get values from your CoreData, NSUserDefaults or do some complex operation on passed values before assigning property values. Thus, you get no default initializer since in most cases, your initializer won’t be as simple as assigning passed values into your properties anyway.

Take-away

Use struct if you just need a container to put some values in and pass around without concurrency issue.

Personally, I use struct whenever a consistency needs to be enforced while passing around multiple values. Kind of like protocol but to serve values. Instead of passing dictionary of values (which is very limited in type-checking), I pass struct of values.

Use class for all else.

Addendum

Also, struct doesn’t support inheritance. If you need that, use class.