Protocols
A protocol defines a blueprint of methods and properties that suit a particular task or piece of functionality. Actual implementation will be provided by other types: structures, classes, enumerations. So it is similar to the interface in Java and Kotlin.
protocol ProtocolA{
var name : String {get}
func greeting()
}
class MyClass: ProtocolA{
// ...
var name: String { return "your name" }
func greeting(){ print("Hello \(name)") }
}
A protocol can inherit one or more other protocols. Also you can combine protocols in typealias statement.
protocol MyProtocol: ProtocolA, ProtocolB {
func extraMethod()
}
typealias MyProtocol = ProtocolA & ProtocolB
Protocol extension can be used for providing default implementation. Also you can add implementation to the specified type.
extension ProtocolA {
var name: String {
return "Harry"
}
func greeting(){
print("Hello \(name)")
}
}
struct A {}
class B {}
extension A: ProtocolA {
// ...
}
extension B: ProtocolA {
// ...
}
Generics can restrict type in where clause. The following extension makes Array instances conform to the TextRepresentable protocol whenever they store elements of a type that conforms to TextRepresentable.
extension Array: TextRepresentable where Element: TextRepresentable {
var textualDescription: String {
let itemsAsText = self.map { $0.textualDescription }
return "[" + itemsAsText.joined(separator: ", ") + "]"
}
}
mutating modifier specifies that method will modify (or mutate) the instance it belongs to.
protocol Togglable {
mutating func toggle()
}
enum OnOffSwitch: Togglable {
case off, on
mutating func toggle() {
switch self {
case .off:
self = .on
case .on:
self = .off
}
}
}
Protocol conformance can be tested by is and as operators.
for item in items {
if let it = item as? rectangle {
print("Hello \(it.greeting())")
} else {
print("Name is unknown")
}
}