Classes, Structures, and Enumerations in Swift
Putting classes, structures, and enumerations together reflects their common features in Swift, but there’s one very important distinction: Enumerations and structures are value types. Instances of enumerations and structures are copied when they are passed to a function or assigned to a variable or constant. This means that you can have multiple copies of a structure or enumeration instance, each with its own values that are independent of the others.
On the other hand, classes are reference types. When they are assigned to a variable or constant or when they are passed to a function, a reference to the instance is what is passed. Because there is a single instance underlying the references passed to functions or assigned to variables or constants, a change to the values of that underlying instance is reflected in all of the copies.
Take a look at the table, which shows you the features available in classes, structures, and enumerations. Most of these features are common to most object-oriented programming languages in one way or another. A few of them are slightly redefined for Swift. They are shown at the left of the table, and are briefly described here.
|Properties||X||X||computed properties only|
Instances: An object which is an actual representation of a class in most object-oriented languages is called an instance. In some object-oriented languages, you can also use a class itself as an object (for example, this is true of Objective-C). For many languages, variables declared as struct or enum, are referred to by the struct or enum name.
In Swift, it is an instance of a struct or enum, but people still often use the type name (as in “myVar is a MyStruct”) rather than as an instance of a particular struct (“myVar is an instance of MyStruct”). Don’t lose sleep over this.
Properties: You can declare properties that may either be stored or computed as they are needed. (Enumerations only support computed properties.)
Methods: You can declare methods that can be accessed through any instance of these objects.
Subscripts: You can declare subscripts that let you access elements of a type instance based on the logic in the subscript. Examples include providing multiple indexing schemes for multi-dimensional objects that may sometimes be accessed as if they were one-dimensional arrays and sometimes using multiple dimensions. They also are useful in managing non-integer indexes.
Initializers: Initializers let you set up the properties for a new instance.
Extensions: Extensions let you add methods and properties without necessarily having the code for the object to which you are adding them. (Only computed properties can be used with enumerations.)
Protocols: You can define methods in a protocol that must be implemented by any object that conforms to that protocol.
Inheritance: Classes can inherit from one another forming a subclass/superclass structure. A class can have any number of subclasses but only one (or no) superclass.
Type casting: You can treat one class as its sub- or superclass if conditions permit. This is basically a standard exercise in logic. UILabel is a subclass of UIView; therefore, all instances of UILabel are also instances of UIView. Not all instances of UIView are instances of UILabel.
Deinitializers: Deinitializers let you clean up just before a class instance is about to be deallocated.
ARC: Automatic reference counting (ARC) allows you to have multiple instances of a class. When you pass them around, they are passed by reference, so that, for example, if you have two instances of UILabel, setting the text for one UILabel doesn’t have anything to do with setting the text for the other label.