Reputation: 569
In Swift, you cannot define default implementations of functions or properties in the Protocol definition itself, i.e.:
protocol Container {
//These are fine
associatedtype Item
mutating func append(_ item: Item)
var count: Int { get set }
subscript(i: Int) -> Item { get }
//These are not fine
var defaultValue: Int = 10
mutating func messWithCount(){
self.count *= 10
}
}
extension Container {
//This is fine though
mutating func messWithCount(){
self.count *= 10
}
}
But you could do so via the Extensions (although Extensions do not support stored properties, they support functions and computed ones - although the stored property issue can be worked around).
What is the explanation behind this? As an add along, what is the explanation for optional func
being only implementable if we mark both the Protocol and the func as @objc
and hence rendering it unusable for Structs/Enums (which are Value not Reference based)?
EDIT: Added in Extension example
Upvotes: 1
Views: 517
Reputation: 2063
The @optional
directive is an Objective-C only directive and has not been translated to Swift. This doesn't mean that you can't use it in Swift, but that you have to expose your Swift code to Objective-C first with he @objc
attribute.
Note that exposing to Obj-C will only make the protocol available to types that are in both Swift and Obj-C, this excludes for example Structs as they are only available in Swift!
To answer your first question, Protocols are here to define and not implement:
A protocol defines a blueprint of methods, properties, and other requirements [...]
And the implementation should thus be supplied by the class/stuct/enum that conforms to it:
The protocol can then be adopted by a class, structure, or enumeration to provide an actual implementation of those requirements
This definition really applies to Protocols we use in our daily lives as well. Take for example the protocol to write a Paper:
The PaperProtocol defines a paper as a document with the following non-nil variables:
What the introduction, chapters and conclusion contain are up to the one implementing them (the writer) and not the protocol.
When we look at the definition of Extensions, we can see that they are here to add (implement) new functionalities:
Extensions add new functionality to an existing class, structure, enumeration, or protocol type. This includes the ability to extend types for which you do not have access to the original source code.
So extending a protocol (which is allowed) gives you the possibility to add new functionality and hereby give a default implementation of a defined method. Doing so will work as a Swift only alternative to the @optional
directive discussed above.
UPDATE:
While giving a default implementation to a protocol function in Switch does make it "optional", it is fundamentally not the same as using the @optional
directive in Objective-C.
In Objective-C, an optional method that is not implemented has no implementation at all so calling it would result in a crash as it does not exist. One would thus have to check if it exists before calling it, in opposition to Swift with an extension default where you can call it safely as a default implementation exists.
An optional in Obj-C would be used like this:
NSString *thisSegmentTitle;
// Verify that the optional method has been implemented
if ([self.dataSource respondsToSelector:@selector(titleForSegmentAtIndex:)]) {
// Call it
thisSegmentTitle = [self.dataSource titleForSegmentAtIndex:index];
} else {
// Do something as fallback
}
Where it's Swift counterpart with extension default would be:
let thisSegmentTitle = self.dataSource.titleForSegmentAtIndex(index)
Upvotes: 1