Extensions
Extensions in Swift add new functionality to an existing class, structure, enumeration, or protocol type. This includes the ability to extend types for which you don't have access to the original source code. Extensions in Swift can:
- Add computed properties and computed type properties
- Define instance methods and type methods
- Provide new initializers
- Define subscripts
- Define and use new nested types
- Make an existing type conform to a protocol
Here are some ways to use extensions:
Adding Methods
You can add new methods to existing types.
extension String {
func shout() -> String {
return self.uppercased() + "!!!"
}
}
print("hello".shout()) // Outputs "HELLO!!!"
Adding Computed Properties
You can add computed instance properties and computed type properties.
extension Int {
var squared: Int {
return self * self
}
}
print(5.squared) // Outputs 25
Adding Initializers
You can add new initializers to existing types. This is particularly useful for adding custom initializers to classes provided by frameworks or libraries.
extension String {
init(_ number: Int) {
self.init(number.description)
}
}
let stringFromInt = String(42)
print(stringFromInt) // Outputs "42"
Adding Subscripts
You can add subscript functionalities to existing types.
extension Array {
subscript(safe index: Int) -> Element? {
return (0..<count).contains(index) ? self[index] : nil
}
}
let array = [1, 2, 3]
print(array[safe: 1]) // Optional(2)
print(array[safe: 5]) // nil
Adding Protocol Conformance
You can also make existing types conform to a protocol.
protocol Nameable {
var name: String { get }
}
extension String: Nameable {
var name: String {
return self
}
}
In this example, the String type automatically conforms to the Nameable protocol because it already has a name property (the string itself).
Extending Nested Types
You can extend nested types using their fully qualified name.
extension ChessBoard.Square {
func description() -> String {
return "This is a \(player) \(piece)"
}
}
Conditional Extensions
You can also extend a generic type conditionally to add functionalities for instances of the type that meet certain criteria.
extension Collection where Element: Numeric {
func sum() -> Element {
return reduce(0, +)
}
}
let numbers = [1, 2, 3, 4]
print(numbers.sum()) // Outputs 10
Extensions can drastically improve code reusability and organization, allowing for a more modular and clean codebase. However, it's crucial to use them judiciously to avoid conflicts and potential misuse.