How is the ampersand in the return signature in Swift used? - swift

I came across the following code:
func makeContentView() -> UIView & UIContentView {
return DatePickerContentView(self)
}
How does the return type of UIView & UIContentView work? This is the first time I came across this. Does this mean we can do multiple &?
I tried to search but I am not familiar with the corresponding technical term.

It's just a way of describing a type. For the notation, read the Protocol Composition section of https://docs.swift.org/swift-book/LanguageGuide/Protocols.html#ID282.
UIView is not a protocol but it does involve inheritance: it's a class. Accordingly, you can compose a maximum of one class with your list of composed protocols. As the doc says:
In addition to its list of protocols, a protocol composition can also contain one class type, which you can use to specify a required superclass.
So this code means the return type here is "a type that inherits from the UIView class and that also adopts the UIContentView protocol."
And yes, you can do composition on multiple protocols. In our code base we often compose ten or twenty protocols in this way.

Related

In swift, why can't I instantiate a protocol when it has an initialiser?

I understand that generally I cannot instantiate a protocol.
But if I include an initialiser in the protocol then surely the compiler knows that when the protocol is used by a struct or class later, it will have an init which it can use?
My code is as below and line:
protocol Solution {
var answer: String { get }
}
protocol Problem {
var pose: String { get }
}
protocol SolvableProblem: Problem {
func solve() -> Solution?
}
protocol ProblemGenerator {
func next() -> SolvableProblem
}
protocol Puzzle {
var problem: Problem { get }
var solution: Solution { get }
init(problem: Problem, solution: Solution)
}
protocol PuzzleGenerator {
func next() -> Puzzle
}
protocol FindBySolvePuzzleGenerator: PuzzleGenerator {
var problemGenerator: ProblemGenerator { get }
}
extension FindBySolvePuzzleGenerator {
func next() -> Puzzle {
while true {
let problem = problemGenerator.next()
if let solution = problem.solve() {
return Puzzle(problem: problem, solution: solution)
}
}
}
}
The line:
return Puzzle(problem: problem, solution: solution)
gives error: Protocol type 'Puzzle' cannot be instantiated
Imagine protocols are adjectives. Movable says you can move it, Red says it has color = "red"... but they don't say what it is. You need a noun. A Red, Movable Car. You can instantiate a Car, even when low on details. You cannot instantiate a Red.
But if I include an initialiser in the protocol then surely the compiler knows that when the protocol is used by a struct or class later, it will have an init which it can use?
Protocols must be adopted by classes, and there might be a dozen different classes that all adopt your Puzzle protocol. The compiler has no idea which of those classes to instantiate.
Protocols give us the power to compose interfaces without the complexity of multiple inheritance. In a multiple inheritance language like C++, you have to deal with the fact that a single class D might inherit from two other classes, B and C, and those two classes might happen to have methods or instance variables with the same name. If they both have a methodA(), and B::methodA() and C::methodA() are different, which one do you use when someone call's D's inherited methodA()? Worse, what if B and C are both derived from a common base class A? Protocols avoid a lot of that by not being directly instantiable, while still providing the interface polymorphism that makes multiple inheritance attractive.
I understand that I can't do it - I just want to understand why the
compiler can't do it?
Because protocols in Swift represent abstraction mechanism. When it comes to abstraction, you could think about it as a template, we don't have to care about the details of how it behaves or what's its properties; Thus it makes no sense to be able to create an object from it.
As a real world example, consider that I just said "Table" (as an abstracted level), I would be pretty sure that you would understand what I am talking about! nevertheless we are not mentioning details about it (such as its material or how many legs it has...); At some point if I said "create a table for me" (instantiate an object) you have the ask me about specs! and that's why the complier won't let you create object directly from a protocol. That's the point of making things to be abstracted.
Also, checking: Why can't an object of abstract class be created? might be helpful.
Unfortunately swift does not allow that even with such "hack"
You would need to use a class that confirms to that protocol as an object you refer to.
When you instantiate an object, the Operating System has to know how to allocate and deal with that kind of object in the memory: Is it a reference type (Classes)? Strong, weak or unowned reference? Or is it a value type (Structs, Strings, Int, etc)?
Reference types are stored in the Heap, while value types live in the Stack. Here is a thorough explanation of the difference between the two.
Only Reference and Value types (objects) can be instantiated. So, only the objects that conform to that protocol can then be instantiated, not the protocol itself. A protocol is not an object, it is a general description or schema of a certain behavior of objects.
As to Initialization, here what the Apple docs say:
Initialization is the process of preparing an instance of a class,
structure, or enumeration for use. This process involves setting an
initial value for each stored property on that instance and performing
any other setup or initialization that is required before the new
instance is ready for use.

How should protocol/implementation pairs be adjusted for the Swift API design guidelines?

In the new Swift API design guidelines, the commonly-used Type suffix for protocols is being dropped. While this is easy to do for protocols that are stand-alone (SequenceType becomes Sequence), I'm not sure how to update my APIs in which a protocol provides the base for an implementation. Here's some examples from popular frameworks:
The Result µframework provides Result, a concrete success/fail enumeration, and ResultType, a generic base protocol for a success/fail type, to which Result conforms.
ReactiveCocoa's main types are Signal and SignalProducer, which are backed by SignalType and SignalProducerType.
In both cases, much of the implementation is in extensions of the protocols, allowing extensions to use the full power of type constraints, and allowing the implementations to be generic. This is different from the case of protocols with AnySequence-style type-erasing types: you aren't really expected to implement these protocols on your own, or unify disparate types.
I would advise using the suffix Protocol. This is consistent with how the standard library have stripped the Type suffix from protocols, as stated in SE-0006:
On high level, the changes can be summarized as follows.
Strip Type suffix from protocol names. In a few special cases this
means adding a Protocol suffix to get out of the way of type names
that are primary (though most of these we expect to be obsoleted by
Swift 3 language features).
For example, GeneratorType was renamed to IteratorProtocol.
And, for example, is also how both Result & ReactiveSwift have updated their APIs for Swift 3. ResultType was renamed to ResultProtocol (in this commit), and SignalType was renamed to SignalProtocol, and SignalProducerType was renamed to SignalProducerProtocol (in this commit).
Although it's worth noting that in a vast majority of these cases, such protocols only exist as a workaround for the lack of parameterised extensions.
For example, we cannot currently say:
struct SomeGenericThing<T> {
var value: T
}
extension <T> Array where Element == SomeGenericThing<T>, T : Comparable {
}
But introducing a protocol allows us to realise the generic placeholder(s) as associated type(s), which we can then use in constraints:
protocol SomeGenericThingProtocol {
associatedtype T
var value: T { get set }
}
struct SomeGenericThing<T> : SomeGenericThingProtocol {
var value: T
}
extension Array where Element : SomeGenericThingProtocol, Element.T : Comparable {
// ...
}
Therefore once parameterised extensions are supported, we'll be able to do away with such protocols.

Abstract methods in Swift?

I have few questions for Swift developers regarding the concept of abstract classes.
How do you define an abstract class in Swift? Is there any way to prevent a class from being instantiated, while providing an initializer for its subclasses to use?
How do you define abstract methods, while implementing others? When defining abstract methods, Apple generally points you to protocols (interfaces). But they only solve the first part of my question, since all of the methods they define are abstract. What do you do when you want to have both abstract and non-abstract methods in your class?
What about generics? You might have thought about using protocols together with extensions (categories). But then there is an issue with generics because protocols can't have generic types, only typealiases.
I have done my homework and I know about solving these issues using methods, such as fatalError() or preconditionFailure() in the superclass and then overriding them in a base class. But that seems like ugly object design to me.
The reason I'm posting this is to find out whether there exists more general and universal solution.
Thanks in advance,
Petr.
As of today (April 7, 2016), the proposal to introduce abstract classes and methods to Swift (SE-0026) has been deferred.
Joe Groff posted the following in swift-evolution-announce on March 7, 2016:
The proposal has been deferred from Swift 3. Discussion centered around whether abstract classes fit in the direction of Swift as a "protocol-oriented" language. Beyond any religious dogmas, Swift intends to be a pragmatic language that lets users get work done. The fact of the matter today is that one of Swift's primary target platforms is the inheritance-heavy Cocoa framework, and that Swift 2's protocols fall short of abstract classes in several respects [...].
We'd like to revisit this feature once the core goals of Swift 3 have been addressed, so we can more accurately consider its value in the context of a more complete generics implementation, and so we can address the finer points of its design.
I encourage you to read the full email, but I think the conclusion is the same as what you came up with in your question: we're currently stuck with the Objective-C way of doing things (raising exceptions).
There is no Abstract concept in Swift. But we can achieve that scenario by using Inheritance concept like the code below:
class ParentVC:UIViewController {
func loadInformation() {
}
}
class ChildVC:ParentVC {
// This is an Abstract Method
override func loadInformation() {
}
}
How do you define abstract methods, while implementing others?
The "swifty" way of achieving this is combining protocols and extensions, sometimes also typealiases. For data, you are going to define abstract properties in your protocol, then re-define them in a concrete class, then unite all that using a typealias and the & operator:
protocol BaseAbstract: class {
var data: String { get set }
func abstractMethod()
func concreteMethod()
}
extension BaseAbstract {
// Define your concrete methods that use the abstract part of the protocol, e.g.:
func concreteMethod() {
if !data.isEmpty {
abstractMethod()
}
}
}
class BaseImpl {
// This is required since we can't define properties in extensions.
// Therefore, we define a class with a concrete property and then
// unite it with the protocol above in the typealias below.
var data: String = "Hello, concrete!"
}
typealias Base = BaseAbstract & BaseImpl // et voila, `Base` is now ready to be subclassed
class Subclass: Base {
func abstractMethod() { // enforced by the compiler
}
}
(It can get tricker if you have generics in this scenario. Currently trying to figure it out.)

What is a "marker protocol" in Swift?

I was searching through some Swift open source code and have now seen the term "marker protocol" pop up twice. From context I'm inferring it as a protocol that exists for code readability reasons, not actually to enforce rules. Can anyone explain exactly what a "marker protocol" is AND why it is used?
Marker protocol is a design pattern borrowed from other object-oriented programming languages that allow protocols or interfaces. The idea is to mark a class for use in a specific way, but without requiring the class to provide any functionality by implementing specific methods. For example, Java used this approach to mark classes serializable.
Here is an example:
protocol Marker {}
class One : Marker {
...
}
class Two { // No marker
...
}
...
if (myObj is Marker) {
... // Objects of class One will pass
... // Objects of class Two will not pass
}
This technique is becoming less relevant when the need to mark classes is addressed explicitly by language. For example, Java could have used annotations for dealing with serializability, in the same way that C# did it using attributes, but the feature had not been available at the time.
Swift is an evolving language that has attributes, but all of them are pre-defined. An addition of user-defined attributes will eliminate the need for marker protocols.

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.