Throughout the past couple of lessons, we've been learning how to use Swift syntax, variables, functions, and control flow structures to develop the building blocks of Swift applications. In the final section of this lesson, we'll learn how to pull all those language components together into Swift's object-oriented classes and structures—the high-level building blocks of most professional Swift applications.
Swift is an object-oriented programming language, and enables the core principles of object-oriented programming. Generally speaking, in object-oriented programming, variables, functions and data structures that implement a functional unit of your program are combined into an object that exists within its own namespace, and is accessed by other objects through filtered, publicly exposed interfaces.
Using Swift, instances are created using both structs and classes. Structs and classes support encapsulation and abstraction, though only classes support inheritance. Both object types—structs and classes—are frequently used in Swift, and neither is better than the other for all use cases.
Virtually all object-oriented languages are based on the concept of organizing units of code into classes that perform a very specific set of actions on a specific set of data.
A class can be thought of as a pattern, such as one a clothes factory might place over a bolt of fabric to cut a new shirt. The pattern (class) has all the dimensions and notations that describe to the tailor what shape the shirt will take. The tailor can use the pattern to create as many shirts as they need—each one perfectly formed by placing the pattern on the raw fabric and cutting around the pattern. Here, the tailor is the Swift runtime, the pattern is the class (or struct) designed by the programmer, and the finished shirt is an object generated by the Swift runtime environment.
While this section isn't a comprehensive tutorial on object-oriented programming, some general guidelines for selecting between classes and structs are the following:
In this lesson, we'll focus on the syntax to define, instantiate, and use your own structs and classes. These techniques are nearly the same for each object type.
A class or struct is defined with the following syntax:
struct
or class
keyword defines a namespace for the class. This namespace is prepended to any symbol definition within the scope of the struct or class when your application is assembled.Internal
, which makes all elements visible to any code in the same module.The following are declarations for a Customer
object—the first declared as a struct and the second as a class:
struct Customer { var name: String var customerNumber: String } class Customer { var name: String var customerNumber: String }
Throughout the last couple of lessons, you've been using structs and classes, for example:
.count
property we often used to count the characters contained in a string.JSONDecoder
class to decode the JSON text in Activity B
.As you develop applications with Swift, you'll use classes and structs frequently, and will often define your own.
Next, you'll solidify your understanding of basic struct and class usage by practicing the creation of each type of object in an activity.
To compare the differences (and similarities) between Swift classes and structs, it's useful to implement the same data structure in both. This is exactly what we'll do now.
Use an Xcode playground to practice how to create Swift structs and classes.
CustomerStructClass.playground
.struct CustomerStruct { }
var customer1 = CustomerStruct()
CustomerType
and variable type
to the struct. Then modify your code to print the current customer.type
to the debug console:struct CustomerStruct { enum CustomerType: String { case gold = "Gold Customer!" case silver = "Silver Customer!" case unknown = "Unknown customer type" } var type: CustomerType? } var customer1 = CustomerStruct() print(customer1.type ?? "invalid customer type")
customer
variable as follows:var customer = CustomerStruct(type: .gold)
class CustomerClass { enum CustomerType: String { case gold = "Gold Customer!" case silver = "Silver Customer!" case unknown = "Unknown customer type" } var type: CustomerType? init(type:CustomerType) { self.type = type } }
CustomerClass
. Because Swift does not automatically create initializers for classes, CustomerClass
includes an initializer to allow its CustomerType
variable to be set on instantiation—just as the automatically created struct initializer does for CustomerStruct
.CustomerClass
, and print its type enum member to the debug console:var customer2 = CustomerClass(type: .silver) print(customer2.type ?? "invalid customer type")