Classes and Structures

Classes and structures are general-purpose, flexible constructs that become the building blocks of your program’s code. You define properties and methods to add functionality to your classes and structures by using exactly the same syntax as for constants, variables, and functions.

Unlike other programming languages, Swift does not require you to create separate interface and implementation files for custom classes and structures. In Swift, you define a class or a structure in a single file, and the external interface to that class or structure is automatically made available for other code to use.

NOTE

An instance of a class is traditionally known as an object. However, Swift classes and structures are much closer in functionality than in other languages, and much of this chapter describes functionality that can apply to instances of either a class or a structure type.

Comparing Classes and Structures

Classes and structures in Swift have many things in common. Both can:

  • Define properties to store values
  • Define methods to provide functionality
  • Define subscripts to provide access to their values using subscript syntax
  • Define initializers to set up their initial state
  • Be extended to expand their functionality beyond a default implementation
  • Conform to protocols to provide standard functionality of a certain kind

For more information, see Properties, Methods, Subscripts, Initialization, Extensions, and Protocols.

Classes have additional capabilities that structures do not:

  • Inheritance enables one class to inherit the characteristics of another.
  • Type casting enables you to check and interpret the type of a class instance at runtime.
  • Deinitializers enable an instance of a class to free up any resources it has assigned.
  • Reference counting allows more than one reference to a class instance.

For more information, see Inheritance, Type Casting, Deinitialization, and Automatic Reference Counting.

NOTE

Structures are always copied when they are passed around in your code, and do not use reference counting.

Definition Syntax

class keyword and structures with the struct keyword. 

class SomeClass {
   // class definition goes here
}
struct SomeStructure {
   // structure definition goes here
}

NOTE

Whenever you define a new class or structure, you effectively define a brand new Swift type. Give types UpperCamelCase names (such as SomeClass and SomeStructure here). Conversely, always give properties and methods lowerCamelCase names (such as frameRate and incrementCount) to differentiate them from type names.

struct Resolution {
   var width = 0
   var height = 0
}
class VideoMode {
   var resolution = Resolution()
   var interlaced = false
   var frameRate = 0.0
   var name: String?
}

Class and Structure Instances:

let someResolution = Resolution()
let someVideoMode = VideoMode()

Structures and classes both use initializer syntax for new instances. 

Accessing Properties

You can access the properties of an instance using dot syntax.

print(“The width of someResolution is (someResolution.width)”)
// Prints “The width of someResolution is 0”

You can drill down into sub-properties, such as the width property in the resolution property of a VideoMode:

print(“The width of someVideoMode is (someVideoMode.resolution.width)”)
// Prints “The width of someVideoMode is 0”

someVideoMode.resolution.width = 1280
print(“The width of someVideoMode is now (someVideoMode.resolution.width)”)
// Prints “The width of someVideoMode is now 1280”

NOTE

Unlike Objective-C, Swift enables you to set sub-properties of a structure property directly. In the last example above, the width property of the resolution property of someVideoMode is set directly, without your needing to set the entire resolution property to a new value.

Memberwise Initializers for Structure Types

All structures have an automatically-generated memberwise initializer, which you can use to initialize the member properties of new structure instances. Initial values for the properties of the new instance can be passed to the memberwise initializer by name:

let vga = Resolution(width: 640, height: 480)

Unlike structures, class instances do not receive a default memberwise initializer. Initializers are described in more detail in Initialization.

Structures and Enumerations Are Value Types

A value type is a type whose value is copied when it is assigned to a variable or constant, or when it is passed to a function.

You’ve actually been using value types extensively throughout the previous chapters. In fact, all of the basic types in Swift—integers, floating-point numbers, Booleans, strings, arrays and dictionaries—are value types, and are implemented as structures behind the scenes.

(참고 closure is reference type)

All structures and enumerations are value types in Swift. This means that any structure and enumeration instances you create—and any value types they have as properties—are always copied when they are passed around in your code.

let hd = Resolution(width: 1920, height: 1080)
var cinema = hd

cinema.width = 2048

print(“cinema is now (cinema.width) pixels wide”)
// Prints “cinema is now 2048 pixels wide”

print(“hd is still (hd.width) pixels wide”)
// Prints “hd is still 1920 pixels wide”

enum CompassPoint {
   case north, south, east, west
}
var currentDirection = CompassPoint.west
let rememberedDirection = currentDirection
currentDirection = .east
if rememberedDirection == .west {
   print(“The remembered direction is still .west”)
}
// Prints “The remembered direction is still .west”

Classes Are Reference Types

let tenEighty = VideoMode()
tenEighty.resolution = hd
tenEighty.interlaced = true
tenEighty.name = “1080i”
tenEighty.frameRate = 25.0

let alsoTenEighty = tenEighty
alsoTenEighty.frameRate = 30.0

print(“The frameRate property of tenEighty is now (tenEighty.frameRate)”)
// Prints “The frameRate property of tenEighty is now 30.0”

Identity Operators

Because classes are reference types, it is possible for multiple constants and variables to refer to the same single instance of a class behind the scenes. (The same is not true for structures and enumerations, because they are always copied when they are assigned to a constant or variable, or passed to a function.)

It can sometimes be useful to find out if two constants or variables refer to exactly the same instance of a class. To enable this, Swift provides two identity operators:

  • Identical to (===)
  • Not identical to (!==)

if tenEighty === alsoTenEighty {
   print(“tenEighty and alsoTenEighty refer to the same VideoMode instance.”)
}
// Prints “tenEighty and alsoTenEighty refer to the same VideoMode instance.”

  • “Identical to” means that two constants or variables of class type refer to exactly the same class instance.
  • “Equal to” means that two instances are considered “equal” or “equivalent” in value, for some appropriate meaning of “equal”, as defined by the type’s designer.

Assignment and Copy Behavior for Strings, Arrays, and Dictionaries

In Swift, many basic data types such as String, Array, and Dictionary are implemented as structures. This means that data such as strings, arrays, and dictionaries are copied when they are assigned to a new constant or variable, or when they are passed to a function or method.

This behavior is different from Foundation: NSString, NSArray, and NSDictionary are implemented as classes, not structures. Strings, arrays, and dictionaries in Foundation are always assigned and passed around as a reference to an existing instance, rather than as a copy.

NOTE

The description above refers to the “copying” of strings, arrays, and dictionaries. The behavior you see in your code will always be as if a copy took place. However, Swift only performs an actual copy behind the scenes when it is absolutely necessary to do so. Swift manages all value copying to ensure optimal performance, and you should not avoid assignment to try to preempt this optimization.

Comments are closed.

Post Navigation