The contents of this page include:
- Enumeration syntax (enumeration Syntax)
- Match enumeration values with
Swith
statements (Matching enumeration values with a Switch Statement)
- Correlation value (associated values)
- Original value (Raw values)
- Recursive enumeration (Recursive enumerations)
Enumerations define a set of related values for a common type, so that you can use them in a safe way in your code.
If you are familiar with the C language, you will know that in C the enumeration corresponds to an integer value. The enumerations in Swift are more flexible and do not have to provide a value for each enumeration member. If you supply an enumeration member with a value (called the "original" value), the type of the value can be a string, a character, or an integer value or a floating-point number.
In addition, enumeration members can specify that any type of related value is stored in an enumeration member value, just like a union (unions) and variant (variants) in other languages. You can define a common set of related members as part of an enumeration, each with a different set of values of the appropriate type associated with it.
In Swift, the enumeration type is a one-class citizen (first-class). They employ a number of features traditionally supported only by Class (class), such as computed attributes (computed properties), which provide additional information about enumerating the current values, instance methods (instance methods), Used to provide and enumerate the functions that are associated with the value represented by the enumeration. Enumerations can also define constructors (initializers) to provide an initial value, extend their functionality on the basis of the original implementation, and can comply with the Protocol (protocols) to provide standard functionality.
For more information, see Properties, Methods (Methods), construction procedures (initialization), extensions (Extensions), and protocols (protocols).
Enumeration syntax
Use enum
keywords to create enumerations and place their entire definition within a pair of curly braces:
enum SomeEnumeration { // 枚举定义放在这里}
Here is an example of the compass in four directions:
enum CompassPoint { case North case South case East case West}
The values defined in the enumeration (for example North
, South
, East
and West
) are the member values (or members) of this enumeration. case
The keyword indicates that a row of new member values will be defined.
Note: Unlike C and Objective-c, Swift's enumeration members are not assigned a default integer value when they are created. In the example above,,, CompassPoint
North
South
East
and West
not implicitly assigned to 0
, 1
, 2
and 3
. Instead, the enumeration members themselves have complete values that are well-defined CompassPoint
types.
Multiple member values can appear on the same line, separated by commas:
enum Planet { case Mercury, Venus, Earth, Mars, Jupiter, Saturn, Uranus, Neptune}
Each enumeration defines a completely new type. Like other types in Swift, their names (such as CompassPoint
and Planet
) must begin with a capital letter. A single-digit name instead of a plural name for an enumeration type to make it easier to read:
var directionToHead = CompassPoint.West
directionToHead
Type can be CompassPoint
inferred when it is initialized with a possible value. Once directionToHead
declared as one CompassPoint
, you can use an abbreviation syntax (.) to set it to another CompassPoint
value:
directionToHead = .East
When directionToHead
the type is known, the enumeration name can be omitted when the value is assigned again. Using an explicit type of enumeration value can make your code more readable.
Match enumeration values and
Switch
Statement
You can use switch
statements to match a single enumeration value:
directionToHead = .Southswitch directionToHead { case .North: print("Lots of planets have a north") case .South: print("Watch out for penguins") case .East: print("Where the sun rises") case .West: print("Where the skies are blue")}// 输出 "Watch out for penguins”
You can understand this code this way:
" directionToHead
the value of the judgment. When it equals .North
, print “Lots of planets have a north”
. When it equals .South
, print “Watch out for penguins”
. ”
And so on.
As described in control flow, the switch
statement must be exhaustive in all cases when judging the value of an enumerated type. If this is omitted .West
, the code above will not compile because it does not take into account CompassPoint
all the members. Mandatory full exhaustive requirements ensure that enumeration members are not accidentally omitted.
When you do not need to match each enumeration member, you can provide a default default
branch to cover all enumerated members that are not explicitly presented:
let somePlanet = Planet.Earthswitch somePlanet {case .Earth: print("Mostly harmless")default: print("Not a safe place for humans")}// 输出 "Mostly harmless”
Correlation value (associated values)
The example in the previous section demonstrates how to define (classify) the members of an enumeration. You can Planet.Earth
set a constant or variable, and look at the value after the assignment. In any case, it is useful to be able to store other types of related values together with member values sometimes. This allows you to store custom information outside of a member's value and allow this information to change every time you use that member in your code.
You can define Swift's enumeration to store any type of related value, and the data type of each member can be different if required. This attribute of the enumeration is similar to the recognizable union (discriminated unions) in other languages, the label union (tagged unions), or the variant (variants).
For example, suppose an inventory tracking system needs to use two different types of barcodes to track goods. Some products are marked with a one-dimensional barcode in upc-a format, which uses numbers 0 through 9. Each barcode has a number representing the "digital system" followed by 5 numbers representing the "Production Code", followed by a 5-bit "Product Code". The last number is the "check" bit to verify that the code is scanned correctly:
Other products are labeled QR code format, it can use any ISO 8859-1 characters, and can encode a maximum of 2,953 characters of the string:
For the inventory tracking system, it is convenient to store the UPC-A code as a tuple of four integer values, and the QR code as a string of any length.
In Swift, you define an enumeration of two commodity barcodes using the following method:
enum Barcode { case UPCA(Int, Int, Int, Int) case QRCode(String)}
The above code can understand this:
"Defines an Barcode
enumeration type named, which can be a UPCA
correlation value (,,, Int
Int
Int
Int
), or a QRCode
string type ( String
) related value. ”
This definition does not provide any Int
or String
actual value, it simply defines the Barcode
Barcode.UPCA
Barcode.QRCode
type of the relevant value when the constant and variable are equal or.
You can then use any one of the barcode types to create new barcodes, such as:
var productBarcode = Barcode.UPCA(8, 85909, 51226, 3)
The above example creates a variable named and productBarcode
assigns it a Barcode.UPCA
related tuple value (8, 85909, 51226, 3)
.
The same product can be assigned to a different type of barcode, such as:
productBarcode = .QRCode("ABCDEFGHIJKLMNOP")
At this point, the original Barcode.UPCA
and its integer value are replaced by the new Barcode.QRCode
and its string values. The bar code constants and variables can store one .UPCA
or .QRCode
the other (along with its associated values), but only one of them will be stored at any given time.
As before, different barcode types can be checked using a switch statement, but this time the correlation value can be extracted as part of the switch statement. You can switch
extract each correlation value in the case branch code as a constant ( let
prefixed) or as a variable ( var
prefixed) to use:
switch productBarcode {case .UPCA(let numberSystem, let manufacturer, let product, let check): print("UPC-A: \(numberSystem), \(manufacturer), \(product), \(check).")case .QRCode(let productCode): print("QR code: \(productCode).")}// 输出 "QR code: ABCDEFGHIJKLMNOP."
If all the relevant values of an enumeration member are extracted as constants, or they are all extracted as variables, for brevity, you can just place one var
or let
label it before the member name:
switch productBarcode {case let .UPCA(numberSystem, manufacturer, product, check): print("UPC-A: \(numberSystem), \(manufacturer), \(product), \(check).")case let .QRCode(productCode): print("QR code: \(productCode).")}// 输出 "QR code: ABCDEFGHIJKLMNOP."
Original value (Raw values)
The bar code example in the related Values section demonstrates how a member of an enumeration declares that they store related values of different types. As an alternative to a related value, an enumeration member can be assigned a value by default (called the original value), where the original values have the same type.
Here is an example of an enumeration member storing ASCII code:
enum ASCIIControlCharacter: Character { case Tab = "\t" case LineFeed = "\n" case CarriageReturn = "\r"}
Here, ASCIIControlCharacter
the original value type of the enumeration type is defined as a character type Character
, and some of the more common ASCII control characters are set. For a description of the character value, see the String and Character section.
The original value can be a string, a character, or any integral or floating-point value. Each original value must be unique within its enumeration declaration.
Attention:
The original value and the correlation value are not the same. When you start defining enumerations in your code, the original values are pre-populated values like the above three ASCII codes. For a particular enumeration member, its original value is always the same. The correlation value is set when you create a new constant or variable based on an enumeration member, and each time you do so, its value can be different.
Implicit assignment of the original value (implicitly Assigned raw values)
You do not need to explicitly assign a value to each member when using an enumeration of the original value as an integer or string type, and Swift will automatically assign you a value.
For example, when an integer is used as the original value, the value of the implicitly assigned value increments by 1. If the first value is not assigned the initial values, it will be automatically set to 0.
The following enumeration is a refinement of the previous Planet
enumeration, using the original integer values to represent the order of each planet in the solar system:
enum Planet: Int { case Mercury = 1, Venus, Earth, Mars, Jupiter, Saturn, Uranus, Neptune}
In the above example, an initial value is assigned, and an Plant.Mercury
1
Planet.Venus
implicit assignment is given 2
, and so on.
When a string is used as the initial value of an enumeration type, the implicit initial value of each enumeration member is the name of the member.
The following example is a CompassPoint
lite version of an enumeration type, using a string as the initial value type, implicitly initialized to the name of each direction:
String { case North, South, East, West}
In the example above, there is CompassPoint.South
an implicit initial value South
, and so on.
The rawValue
original value of the enumeration member can be accessed by using the properties of the enumeration member:
let earthsOrder = Planet.Earth.rawValue// earthsOrder 值为 3let sunsetDirection = CompassPoint.West.rawValue// sunsetDirection 值为 "West"
Initialize enumeration variables with raw values (Initializing from a raw value)
If the original value is used when defining an enumeration type, an initialization method is automatically obtained, which takes the original value type as an argument, and the return value is an enumeration member or nil
. You can use this initialization method to create a new enumeration variable.
This example creates an enumeration member from the original value 7
:
let possiblePlanet = Planet(rawValue: 7)// possiblePlanet 类型为 Planet? 值为 Planet.Uranus
However, not all possible Int
values can be found for a matching planet. Because of this, the constructor can return an optional enumeration member. In the example above, possiblePlanet
it is the Planet?
type, or "optional Planet
".
Note: The original value constructor is a failed constructor, because not every original value has an enumeration member corresponding to it. For more information, see failed constructors
If you are trying to find a planet with a position of 9, the optional value returned by the parameter for the rawValue
constructor Planet
will be nil
:
let positiontofind = 9 if Let someplanet = Planet (rawvalue:positiontofind) {switch so meplanet {case. Earth: print ( "Mostly harmless") print ( "not a safe place for Humans")}} else {print (" there isn ' t a planet at position \ ( Positiontofind)}//output "there isn ' t a planet at position 9
This example uses an optional binding (optional binding) to 9
attempt to access a planet by its original value. if let somePlanet = Planet(rawValue: 9)
statement to obtain an optional Planet
, if optional Planet
can be obtained, set to somePlanet
the optional Planet
content. In this example, the location 9
of the planet cannot be retrieved, so the else
branch is executed.
Recursive enumeration (Recursive enumerations)
When describing an operator, it is convenient to use an enumeration type to model the data, because it is a fixed enumerable to consider. The operator can concatenate two arithmetic expressions consisting of numbers, for example, to 5
concatenate into complex expressions 5+4
.
An important feature of arithmetic expressions is that expressions can be nested. For example, the expression (5 + 4) * 2
multiplication sign to the right is a number, and the left is another expression. Because the data is nested, the enumeration type used to store the data might support this nesting ———— this means that enumeration types need to support recursion.
递归枚举(recursive enumeration)
is an enumeration type that represents the enumeration in which one or more enumeration members have other members of the enumeration as related values. When recursive enumeration is used, the compiler inserts a middle layer. You can add a member before enumeration indirect
to indicate that the member is recursive.
For example, in the following example, an enumeration type stores a simple arithmetic expression:
enum ArithmeticExpression { case Number(Int) indirect case Addition(ArithmeticExpression, ArithmeticExpression) indirect case Multiplication(ArithmeticExpression, ArithmeticExpression)}
You can also add a keyword at the beginning of an enumeration type indirect
to indicate that all its members are recursive:
indirect enum ArithmeticExpression { case Number(Int) case Addition(ArithmeticExpression, ArithmeticExpression) case Multiplication(ArithmeticExpression, ArithmeticExpression)}
The enumerated types defined above can store three arithmetic expressions: a pure number, an addition of two expressions, and a multiplication of two expressions. Addition
Multiplication
The values associated with the member are also arithmetic expressions ———— These related values make nested expressions possible.
Recursive functions can intuitively use data structures that have recursive properties. For example, here is a function that computes an arithmetic expression:
FuncEvaluate(expression:arithmeticexpression), Int {Switch Expression {Case. Number (LetValue):ReturnValueCase. Addition (let left, let right): return Evaluate (left) + evaluate (right) case. Multiplication (let left, let right): return Evaluate (left) * Evaluate (right)}} //calculation (5 + 4) * 2let five = Arithmeticexpression.number (5) let four = Arithmeticexpression.number ( 4) let sum = arithmeticexpression.addition (five, four) let Product = Arithmeticexpression.multiplication (sum, arithmeticexpression.number (2)) print (Evaluate (product)) //Output "" "
If the function encounters a pure number, it returns the value of the number directly. If an addition or multiplication is encountered, the values of the left and right expressions are computed separately and then added or multiplied.
Swift Learning note-enumeration (enumerations)