Differences in usage

Add a new page to your Playground and give it a name again. Something such as Values vs References would be a good name for your new page. Add the following code to your Playground:

protocol PetProtocol {
  var name: String { get }
  var ownerName: String { get set }
}

class Animal {
  let name: String

  init(name: String) {
    self.name = name
  }
}

class Pet: Animal, PetProtocol {
  var ownerName: String

  init(name: String, ownerName: String) {
    self.ownerName = ownerName

    super.init(name: name)
  }
}

This code defines a PetProtocol that requires two properties to exist on all objects that conform to this protocol. The name property is defined as a constant since it only needs it to be gettable, and ownerName is a variable since it requires both get and set. The code also defines an Animal and Pet class. Pet is a subclass of Animal, and it conforms to PetProtocol because Animal satisfies the name constant requirement and Pet itself satisfies the ownerName variable.

Try changing the class declarations to struct. Your Playground will not compile now because structs cannot inherit from other objects like classes can. This is a limitation that is sometimes frustrating because you can end up with a lot of code duplication. Imagine that, in addition to Pet, you would like to create more types of animals, such as a WildAnimal, SeaCreature, this would be easy to achieve with classes because you can inherit from Animal. This is not possible with structs, so you would implement all these types as structs they would need to duplicate their Animal logic.

Another difference between value types and reference types is how they act when they are passed around. Add the following code to your Playground:

class ImageInformation {
  var name: String
  var width: Int
  var height: Int

  init(name: String, width: Int, height: Int) {
    self.name = name
    self.width = width
    self.height = height
  }
}

struct ImageLocation {
  let location: String
  let isRemote: Bool
  var isLoaded: Bool
}

let info = ImageInformation(name: "ImageName", width: 100, height: 100)
let location = ImageLocation(location: "ImageLocation", isRemote: false, isLoaded: false)

The declarations for info and location look very similar, but their underlying types are entirely different. Try writing a function that takes both ImageLocation and ImageInformation as an argument. And then try updating the isLoaded property of location and changing the name of info. The compiler will complain when you try to set isLoaded because the argument for ImageLocation is a let constant. The reason for this was described earlier in the discussion on value types.

Value types are passed around by value, meaning that changing a property of the argument will change the value altogether. Arguments for a function are always constants. This might not be obvious when you use a Reference type though, because it is perfectly fine to change the name property on ImageInformation inside of a function. This is because you don't pass the entire value around when you pass a reference type to a function. You pass the reference to the memory address around. This means that instead of the value being a constant, the underlying memory address is a constant. This, in turn, means that you can change whatever is in memory as much as you like, you just can't change the address that a constant points to.

Imagine that you must drive to somebody's house and they send you the address where they live. This is what it's like to pass around a reference type. Rather than sending you their entire house, they send you the address for their house. While you are driving to their house, the house can change in many ways. The owner could paint it, replace windows, doors, anything. In the end, you will still find the house because you received the address for this house and, as long as the owner doesn't move to a different address, you will find the correct house.

If you change this analogy to use value types, the person whose house you're looking for will simply send you a full copy of their house. So rather than you driving toward their house based on the address, they won't give you an address, they will just send you their whole house. If the owner makes changes to their copy of the house, you won't be able to see them reflected on your copy of the house unless they send you a new copy. This is also true for any modifications you make to your copy of the house.

You can imagine that in some cases it can be very efficient to send somebody a copy of something rather than the address. The sample of a house might be a bit extreme, but I'm pretty sure that if you order a parcel, you would much rather receive the parcel itself than receiving an address to fetch the parcel. This sort of efficiency is what you will learn about next by comparing how value types and reference types behave in terms of memory allocation.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset