Why must Protocol defaults be implemented via Extensions in Swift? - swift

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

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:
Introduction
Chapters
Conclusion
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)

Related

Swift - Why it's possible to call the empty init of protocol-type OptionSet?

I'm trying to understand Swift features by learning the standard library. But I found an unclear case with OptionSet protocol from Swift module.
Let's test the following code
let y: NSOrderedCollectionDifferenceCalculationOptions = .init()
Struct NSOrderedCollectionDifferenceCalculationOptions is declared in Foundation module and it inherits OptionSet. The code provided above is compilable, but why? If you click on .init()'s Jump to defenition, the source of OptionSet protocol will open. But why it's possible to call the init from inherited protocol type?
Thanks!
Basically it's just a matter of understanding what a protocol extension is. A protocol extension has the ability not merely to declare a requirement (e.g. an adopter of this protocol must declare a certain function) but to fulfill that requirement (i.e. provide an implementation for that function).
Thus, when you read in the headers
extension OptionSet where Self.RawValue : FixedWidthInteger {
/// Creates an empty option set.
/// This initializer creates an option set with a raw value of zero.
#inlinable public init()
}
...you are being told that OptionSet over an integer raw value acquires from this protocol extension an init implementation.

What's the mechanics behind extension's methods overriding with '#objc' attribute?

Kind of nerd question. It's unclear to me, what exactly makes this code works:
class Shape { }
extension Shape {
#objc func redraw() {
print("from ext")
}
}
class Circle: Shape { }
class Line: Shape {
override func redraw() { // Compiler error: Declarations from extensions cannot be overridden yet
print("from subclass")
}
}
let line = Line()
let shape:Shape = line
let circle = Circle()
line.redraw() //from subclass
circle.redraw() //from ext
shape.redraw() //from subclass
If I omit #objc keyword in extension, the code won't compile - it's expected behaviour since methods in extension use static method dispatch -> cannot be overridden.
But why adding #objc makes it work? According to documentation and most articles, all is #objc doing is making things visible to Objective-c runtime. To change method dispatch type there is a special keyword - dynamic. But seems it is not necessary here!
Help me figure out, why is adding #objc (and omitting dynamic) makes such things possible.
Extensions,
as the name already says, are supposed to extend/add/include methods
to an existing implementation, making them one of the most beautiful
things about Objective-C, and now Swift, since you can add code to a
class or framework you do not own. Therefore, it makes sense that
you’re not supposed to “replace” code in extensions, conceptually
speaking.
That’s why the compiler complains when you try to do it.
Also Check out this answer.
however this seems to be a support issue too, as swift compiler simply throw this error:
overriding non-#objc declarations from extensions is not supported.
According to Apple,
Extensions can add new functionality to a type, but they cannot
override existing functionality.
But that is not the case, as we are overriding from the extension not vice versa,
which takes us back to the declaration of extension.
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 (known as retroactive modeling). Extensions are similar to categories in Objective-C. (Unlike Objective-C categories, Swift extensions do not have names.) Here.
Going back to the legacy topic swift compiler vs Objc compiler,
Dynamic dispatch vs. Static dispatch .
And there is no official documentation from apple on why this is not supported from the swift compiler or if they have any future plans to fix this or consider it an issue at all.
However, there’s no such thing as Swift dynamic dispatch; we only have
the Objective-C runtime’s dynamic dispatch. That means you can’t have
just dynamic and you must write #objc dynamic. So this is effectively
the same situation as before, just made explicit.
And here is a great article talking about this topic deeply.

How to determine which members to implement while conforming to a protocol in Swift

I'm learning Swift by playing around with Swift collections. I wanted to create my own Sequence and I know to that I have to conform to SequenceType protocol.
How should I know which members of the protocol do I have to implement? Apple documentation shows a lot of methods for the SequenceType protocol (http://developer.apple.com/library/mac/documentation/Swift/Reference/Swift_SequenceType_Protocol/index.html), eg. dropLast(_:Int), generate(), underestimateCount(), etc.
But it turns out that I only have to provide generate() method and the compiler is happy:
class MySequence : SequenceType {
func generate() -> MyGenerator{
return MyGenerator(total: 6)
}
}
(if not the various blog posts I wouldn't know which of the SequenceType members have to be implemented)
How to determine which member needs to be implemented while conforming to a protocol?
I've seen that some methods are marked with the Default implementation tag. But, for instance, the dropLast(_: Int) -> Self.SubSequence is not marked with such tag and I don't have to implement it.
If you take a look at the API documentation, you'll notice that some of the methods are marked with Default implementation. This means that the implementation for that method has been defined in an extension, and as such, you don't need to override them unless you want to modify the default behavior. The reason this doesn't work for generate(), which has default implementations, is because its default implementations have generic constraints that prevent them from handling all cases.
The ones for underestimateCount() and the other methods you mentioned have a default implementation without constraints, meaning you do not need to override them.
For dropLast(_: Int) specifically, it actually does have a version specified with Default implementation, namely dropLast(_: Int) -> AnySequence<Self.Generator.Element> Default Implementation. Even though they're separate in the API docs, this method will suffice since it has the same parameter signature as the required method in the protocol.

Is there a difference between Swift 2.0 protocol extensions and Java/C# abstract classes?

With the addition of protocol extensions in Swift 2.0, it seems like protocols have basically become Java/C# abstract classes. The only difference that I can see is that abstract classes limit to single inheritance, whereas a Swift type can conform to any number of protocols.
Is this a correct understanding of protocols in Swift 2.0, or are there other differences?
There are several important differences...
Protocol extensions can work with value types as well as classes.
Value types are structs and enums. For example, you could extend IntegerArithmeticType to add an isPrime property to all integer types (UInt8, Int32, etc). Or you can combine protocol extensions with struct extensions to add the same functionality to multiple existing types — say, adding vector arithmetic support to both CGPoint and CGVector.
Java and C# don't really have user-creatable/extensible "plain old data" types at a language level, so there's not really an analogue here. Swift uses value types a lot — unlike ObjC, C#, and Java, in Swift even collections are copy-on-write value types. This helps to solve a lot of problems about mutability and thread-safety, so making your own value types instead of always using classes can help you write better code. (See Building Better Apps with Value Types in Swift from WWDC15.)
Protocol extensions can be constrained.
For example, you can have an extension that adds methods to CollectionType only when the collection's underlying element type meets some criteria. Here's one that finds the maximum element of a collection — on a collection of numbers or strings, this property shows up, but on a collection of, say, UIViews (which aren't Comparable), this property doesn't exist.
extension CollectionType where Self.Generator.Element: Comparable {
var max: Self.Generator.Element {
var best = self[self.startIndex]
for elt in self {
if elt > best {
best = elt
}
}
return best
}
}
(Hat tip: this example showed up on the excellent NSBlog just today.)
There's some more good examples of constrained protocol extensions in these WWDC15 talks (and probably more, too, but I'm not caught up on videos yet):
Protocol-Oriented Programming in Swift
Swift in Practice
Abstract classes—in whatever language, including ObjC or Swift where they're a coding convention rather than a language feature—work along class inheritance lines, so all subclasses inherit the abstract class functionality whether it makes sense or not.
Protocols can choose static or dynamic dispatch.
This one's more of a head-scratcher, but can be really powerful if used well. Here's a basic example (again from NSBlog):
protocol P {
func a()
}
extension P {
func a() { print("default implementation of A") }
func b() { print("default implementation of B") }
}
struct S: P {
func a() { print("specialized implementation of A") }
func b() { print("specialized implementation of B") }
}
let p: P = S()
p.a() // -> "specialized implementation of A"
p.b() // -> "default implementation of B"
As Apple notes in Protocol-Oriented Programming in Swift, you can use this to choose which functions should be override points that can be customized by clients that adopt a protocol, and which functions should always be standard functionality provided by the protocol.
A type can gain extension functionality from multiple protocols.
As you've noted already, protocol conformance is a form of multiple inheritance. If your type conforms to multiple protocols, and those protocols have extensions, your type gains the features of all extensions whose constraints it meets.
You might be aware of other languages that offer multiple inheritance for classes, where that opens an ugly can of worms because you don't know what can happen if you inherit from multiple classes that have the same members or functions. Swift 2 is a bit better in this regard:
Conflicts between protocol extensions are always resolved in favor of the most constrained extension. So, for example, a method on collections of views always wins over the same-named method on arbitrary collections (which in turn wins over the same-named methods on arbitrary sequences, because CollectionType is a subtype of SequenceType).
Calling an API that's otherwise conflicting is a compile error, not a runtime ambiguity.
Protocols (and extensions) can't create storage.
A protocol definition can require that types adopting the protocol must implement a property:
protocol Named {
var name: String { get } // or { get set } for readwrite
}
A type adopting the protocol can choose whether to implement that as a stored property or a computed property, but either way, the adopting type must declare its implementation the property.
An extension can implement a computed property, but an extension cannot add a stored property. This is true whether it's a protocol extension or an extension of a specific type (class, struct, or enum).
By contrast, a class can add stored properties to be used by a subclass. And while there are no language features in Swift to enforce that a superclass be abstract (that is, you can't make the compiler forbid instance creation), you can always create "abstract" superclasses informally if you want to make use of this ability.

Swift and using class extension

I don't understand why programmers use the extension keyword in their class implementation. You can read in other topics that code is then more semantically separated and etc. But when I work with my own code, it feels clearer to me to use // MARK - Something. Then when you use methods list (ctrl+6) in Xcode, everything is seen at first look.
In Apple documentation you can read:
“Extensions add new functionality to an existing class, structure, or enumeration type.”
So why not write my own code directly inside my own class? Unlike when I want to extend functionality of some foreign class, like NSURLSession or Dictionary, where you have to use extensions.
Mattt Thompson use extension in his Alamofire library, maybe he can give me little explanation, why he chose this approach.
For me it seems completely reasonable since you can use extensions to expose different parts of logic to different extensions. This can also be used to make class conformance to protocols more readable, for instance
class ViewController: UIViewController {
...
}
extension ViewController: UITableViewDelegate {
...
}
extension ViewController: UITableViewDataSource {
...
}
extension ViewController: UITextFieldDelegate {
...
}
Protocol methods are separated in different extensions for clarity, this seems to be far better to read than lets say:
class ViewController: UIViewController, UITableViewDelegate, UITableViewDataSource, UITextFieldDelegate {}
So, I'd say there's no harm in using extensions to make your own code more readable, not just to extend already existing classes from SDK. Using extensions you can avoid having huge chunks of code in your controllers and split functionality into easily readable parts, so there's no disadvantage of using those.
Using extensions allows you to keep your declaration of protocol conformance next to the methods that implement that protocol.
If there were no extensions, imagine declaring your type as:
struct Queue<T>: SequenceType, ArrayLiteralConvertible, Equatable, Printable, Deflectable, VariousOtherables {
// lotsa code...
// and here we find the implementation of ArrayLiteralConvertible
/// Create an instance containing `elements`.
init(arrayLiteral elements: T…) {
etc
}
}
Contrast this with using extensions, where you bundle together the implementation of the protocols with those specific methods that implement it:
struct Queue<T> {
// here go the basics of queue - the essential member variables,
// maybe the enqueue and dequeue methods
}
extension SequenceType {
// here go just the specifics of what you need for a sequence type
typealias Generator = GeneratorOf<T>
func generate() -> Generator {
return GeneratorOf {
// etc.
}
}
}
extension Queue: ArrayLiteralConvertible {
init(arrayLiteral elements: T...) {
// etc.
}
}
Yes, you can mark your protocol implementations with // MARK (and bear in mind, you can combine both techniques), but you would still be split across the top of the file, where the declaration of protocol support would be, and the body of the file, where your implementation is.
Also, bear in mind if you’re implementing a protocol, you will get helpful (if slightly verbose) feedback from the IDE as you go, telling you what you’ve got left to implement. Using extensions to do each protocol one by one makes it (for me) far easier than doing it all in one go (or hopping back and forth from top to bottom as you add them).
Given this, it’s then natural to group other, non-protocol but related methods into extensions as well.
I actually find it frustrating occasionally when you can’t do this. For example,
extension Queue: CollectionType {
// amongst other things, subscript get:
subscript(idx: Index) -> T {
// etc
}
}
// all MutableCollectionType adds is a subscript setter
extension Queue: MutableCollectionType {
// this is not valid - you’re redeclaring subscript(Index)
subscript(idx: Int) -> T {
// and this is not valid - you must declare
// a get when you declare a set
set(val) {
// etc
}
}
}
So you have to implement both within the same extension.