Difference between revisions of "Enum"
Jeff-strong (talk | contribs) m (Editorial review and minor corrections) |
|||
(3 intermediate revisions by 2 users not shown) | |||
Line 1: | Line 1: | ||
Enumerations offer many characteristics that classes don't have, such as computed properties to provide extra information about the current value of the enumeration, and instance methods to give functionality related to the values it represents. | Enumerations offer many characteristics that classes don't have, such as computed properties to provide extra information about the current value of the enumeration, and instance methods to give functionality related to the values it represents. | ||
Enumerations can be used to define initializers and provide a starting case value | Enumerations can be used to define initializers and provide a starting case value. They can also be extended to add more features. Enumerations can also standardize on features to offer standard functionality. | ||
== Curriculum == | == Curriculum == | ||
{{MerlinCurriculumData|{{ROOTPAGENAME}}}} | {{MerlinCurriculumData|{{ROOTPAGENAME}}}} | ||
Line 8: | Line 8: | ||
The enum keyword is used to declare enumerations, and you must place their entire definition inside a pair of braces. | The enum keyword is used to declare enumerations, and you must place their entire definition inside a pair of braces. | ||
The cases of an enumeration are the enum values (such as "first," "second," "third," and "fourth") that define it. The case keyword is used to introduce new case values. A single line | The cases of an enumeration are the enum values (such as "first," "second," "third," and "fourth") that define it. The case keyword is used to introduce new case values. A single line can contain many cases, separated by commas. | ||
Enumerations are a class-based extension to the syntax. They extend the language's flexibility by giving classes and structs more ways of defining components via names, types, and protocols. Enums can be used in place of enumeration literals to define methods or properties. An enum is always an instance of one | Enumerations are a class-based extension to the syntax. They extend the language's flexibility by giving classes and structs more ways of defining components via names, types, and protocols. Enums can be used in place of enumeration literals to define methods or properties. An enum is always an instance of one type. | ||
<syntaxhighlight lang="swift"> | <syntaxhighlight lang="swift"> | ||
Line 22: | Line 22: | ||
{{CodeExplorer | {{CodeExplorer | ||
|exerciseID=1 | |exerciseID=1 | ||
| | |language=swift | ||
|height=400 | |height=400 | ||
|initialCode=import Foundation | |initialCode=import Foundation | ||
Line 46: | Line 46: | ||
}} | }} | ||
==Enum Initialization from String== | ==Enum Initialization from a String== | ||
In Swift, it is possible to initialize enum from | In Swift, it is possible to initialize enum from a String type. Enum can be initialized with a specific case or all cases of an enum. The following example shows how to do this: | ||
{{CodeExplorer | {{CodeExplorer | ||
|exerciseID=10 | |exerciseID=10 | ||
| | |language=swift | ||
|height=300 | |height=300 | ||
|initialCode=import Foundation | |initialCode=import Foundation | ||
enum Genders { | enum Genders: String { | ||
case male | |||
case male | case female | ||
case female | |||
} | } | ||
let myGender = Genders(rawValue: "male")! | |||
let yourGender = Genders(rawValue: "female")! | |||
print(myGender) | |||
print(yourGender) | |||
}} | }} | ||
==Iterating Over Enums== | ==Iterating Over Enums== | ||
Sometimes, it's nice to have a collection of all | Sometimes, it's nice to have a collection of all the instances in an enumeration. You can do so by adding <syntaxhighlight lang="swift" inline> :CaseIterable </syntaxhighlight> after the name of the enumeration. The <syntaxhighlight lang="swift" inline> allCases | ||
</syntaxhighlight> property of the enumeration type returns a list containing all cases. | </syntaxhighlight> property of the enumeration type returns a list containing all cases. | ||
{{CodeExplorer | {{CodeExplorer | ||
|exerciseID=2 | |exerciseID=2 | ||
| | |language=swift | ||
|height=400 | |height=400 | ||
|initialCode=import Foundation | |initialCode=import Foundation | ||
Line 97: | Line 91: | ||
== Assigning Values to Enums == | == Assigning Values to Enums == | ||
We've seen how enums are | We've seen how enums are used for switches and conditions, but can they also store a value directly? You can refer to predetermined values using rawValue. Let's try to do this by extending our earlier example and adding value. | ||
It's also important to remember that you must label your enum with a data type before attempting to set a value to it. Now, we can assign values to our enum items and extract the value directly with the <syntaxhighlight lang="swift" inline>.rawValue</syntaxhighlight> syntax. | It's also important to remember that you must label your enum with a data type before attempting to set a value to it. Now, we can assign values to our enum items and extract the value directly with the <syntaxhighlight lang="swift" inline>.rawValue</syntaxhighlight> syntax. | ||
Line 103: | Line 97: | ||
{{CodeExplorer | {{CodeExplorer | ||
|exerciseID=3 | |exerciseID=3 | ||
| | |language=swift | ||
|height=400 | |height=400 | ||
|initialCode=import Foundation | |initialCode=import Foundation | ||
Line 127: | Line 121: | ||
<syntaxhighlight lang="swift"> enum MyEnum { case some(String) case none } </syntaxhighlight> | <syntaxhighlight lang="swift"> enum MyEnum { case some(String) case none } </syntaxhighlight> | ||
If we were using this enum there would be no way for us to tell if it was safe to call <syntaxhighlight lang="swift" inline>.Some("val")</syntaxhighlight> or <syntaxhighlight lang="swift" inline>.None</syntaxhighlight> on this instance because both cases map onto the same underlying numeric value (zero). | If we were using this enum, there would be no way for us to tell if it was safe to call <syntaxhighlight lang="swift" inline>.Some("val")</syntaxhighlight> or <syntaxhighlight lang="swift" inline>.None</syntaxhighlight> on this instance because both cases map onto the same underlying numeric value (zero). | ||
We could also use associated values: | We could also use associated values: | ||
Line 140: | Line 134: | ||
There is no doubt that we should always prefer them over other options for two reasons: | There is no doubt that we should always prefer them over other options for two reasons: | ||
#They avoid creating ad-hoc classes and subclasses just to agree with the compiler on how our data is structured and what it can do. Note that even if we don't need any of these features, sometimes Swift forces us to create those extra classes/subclasses anyway (e.g., when we use an enum as a property's type) so it's better not to have them in the first place. | |||
#They allow us to encode additional information about each case such as its name or associated values etc., so we can retrieve this information for debugging purposes or just provide a better representation to the user of what this data represents. | |||
But it's also important to remember that just because we can create an enum with associated values, doesn't mean that we should always do so. We know that if the compiler enforces something by design, it's usually a good programming practice but the reverse is not necessarily true. Having many cases in an enum might make sense for some types of data (e.g. representing different units of measurement), but not for others (e.g. representing different accounts). It truly depends on our application and what each case represents within it. | But it's also important to remember that just because we can create an enum with associated values, it doesn't mean that we should always do so. We know that if the compiler enforces something by design, it's usually a good programming practice, but the reverse is not necessarily true. Having many cases in an enum might make sense for some types of data (e.g., representing different units of measurement), but not for others (e.g., representing different accounts). It truly depends on our application and what each case represents within it. |
Latest revision as of 09:11, 11 February 2023
Enumerations offer many characteristics that classes don't have, such as computed properties to provide extra information about the current value of the enumeration, and instance methods to give functionality related to the values it represents.
Enumerations can be used to define initializers and provide a starting case value. They can also be extended to add more features. Enumerations can also standardize on features to offer standard functionality.
Curriculum[edit]
Coder Merlin™ Computer Science Curriculum Data | |
Unit: Experience Name: Enum () Next Experience: () Knowledge and skills: noneSome use of "" in your query was not closed by a matching "". Topic areas: none Classroom time (average): Study time (average): Successful completion requires knowledge: none Successful completion requires skills: none |
Basic Enum Syntax in Swift[edit]
The enum keyword is used to declare enumerations, and you must place their entire definition inside a pair of braces.
The cases of an enumeration are the enum values (such as "first," "second," "third," and "fourth") that define it. The case keyword is used to introduce new case values. A single line can contain many cases, separated by commas.
Enumerations are a class-based extension to the syntax. They extend the language's flexibility by giving classes and structs more ways of defining components via names, types, and protocols. Enums can be used in place of enumeration literals to define methods or properties. An enum is always an instance of one type.
enum RacePlaces {
case first
case second
case third
}
Now that this is established, it can be used like this:
Enum Initialization from a String[edit]
In Swift, it is possible to initialize enum from a String type. Enum can be initialized with a specific case or all cases of an enum. The following example shows how to do this:
Iterating Over Enums[edit]
Sometimes, it's nice to have a collection of all the instances in an enumeration. You can do so by adding :CaseIterable
after the name of the enumeration. The allCases
property of the enumeration type returns a list containing all cases.
Assigning Values to Enums[edit]
We've seen how enums are used for switches and conditions, but can they also store a value directly? You can refer to predetermined values using rawValue. Let's try to do this by extending our earlier example and adding value.
It's also important to remember that you must label your enum with a data type before attempting to set a value to it. Now, we can assign values to our enum items and extract the value directly with the .rawValue
syntax.
Associated Values[edit]
Swift's associated values refer to the ability of a type to store one of several possible values. Associated values allow Swift to be more expressive than languages like C, allowing us to provide semantic names for each possible value of a type. The semantics remain transparent with the compiler checking that it is used consistently throughout the codebase.
Why are associated types useful? One example of this is in enumerations. Let's look at an example:
enum MyEnum { case some(String) case none }
If we were using this enum, there would be no way for us to tell if it was safe to call .Some("val")
or .None
on this instance because both cases map onto the same underlying numeric value (zero).
We could also use associated values:
enum MyEnum { case some(String) case none associatedtype OtherT = String }
Now we've introduced an Associated Type 'OtherT' which is a String. This allows us to separate out our types and make sure that any code calling these enums knows what the context of the data is, ensuring safety. Now we've introduced an Associated Type 'OtherT' which is a String. This allows us to separate out our types and make sure that any code calling these enums knows what the context of the data is, ensuring safety.
Conclusion[edit]
When programming in Swift, enumerations are very useful because they avoid the need to create a new type every time we want to provide a different value.
There is no doubt that we should always prefer them over other options for two reasons:
- They avoid creating ad-hoc classes and subclasses just to agree with the compiler on how our data is structured and what it can do. Note that even if we don't need any of these features, sometimes Swift forces us to create those extra classes/subclasses anyway (e.g., when we use an enum as a property's type) so it's better not to have them in the first place.
- They allow us to encode additional information about each case such as its name or associated values etc., so we can retrieve this information for debugging purposes or just provide a better representation to the user of what this data represents.
But it's also important to remember that just because we can create an enum with associated values, it doesn't mean that we should always do so. We know that if the compiler enforces something by design, it's usually a good programming practice, but the reverse is not necessarily true. Having many cases in an enum might make sense for some types of data (e.g., representing different units of measurement), but not for others (e.g., representing different accounts). It truly depends on our application and what each case represents within it.