Constrain inherited associated type in a protocol - swift

I would like to define a Swift protocol that is a also a sequence with an element that conforms to another, specific protocol. Ideally, I'd like to write something like this:
protocol A {
var container: Container { get }
}
protocol Container: Sequence where Iterator.Element: A {
...
}
Unfortunately, Swift doesn't currently allow where clauses in a protocol definition (and it also doesn't allow to use protocols with associated types as type constraints). Is there any way I can still do this? Containers (and ideally A's) should be able to have different backing implementation.
Edit: I know that I can move the sequence to a type-erased property of Container, which will solve all the problems at the expense of introducing unnecessary lexical overhead. Still, I'm interested in a solution which does not 'cheats' its way out of the type system.

Related

Swift: Protocol With associatedType

I have a question about Protocol with associated type, why I can not make the protocol a type of my instance for example:
I know I can use Type Erasure to fix the issue, but why protocol with an associated type does not like to be a type of an instance, and if you will say because the associated type is also used as a constraint, well I want to implement the properties inside the protocol not inside its extensions since protocol extensions has the power to control who can access its properties, why we still have this issue.
Thank you.
There are lots of articles and answers (like this one) out there describing why but in summary, It needs associatedtype. Variables can not have an associatedtype. So alongside with Type Erasure method (that you don't want), you can simply make it opaque with adding some keyword to the type:
var objectA: some ProtocolA = A()

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.

Swift: How to conform to protocol with associated types if I have two types to associate?

OK weird question perhaps, and it's only because I don't really know what I'm asking for so I'll try to describe it best I can. Please direct me appropriately if this has been asked before.
So I'm using the awesome Codable protocol with pretty much all my models and I'm making a class that handles some storing, let's call it Storage<Model: Codable> which has a generic type conforming to Codable because one instance of this class will handle storage for one type of model.
Now I need to be notified when things change in the Storage instance, like stuff getting written to disk and deletions. So I make a new protocol StorageListener that declares functions like func storage(_ storage: Storage<CodableType>, didRemoveModelForKey key: String). Now since this uses the Storage type which requires use of a generic Model an associated type must be declared: associatedtype CodableType: Codable.
So I now use type erasure to make an AnyStorageListener<AnyCodableType: Codable>: StorageListener, that I can store in an array in my Storage class.
Now this is fine, I can just conform my ViewModel or whatever to StorageListener and declare the typealias CodableType = MyModel but what if I need my ViewModel to listen to two Storages of different types?
What I've come up with is using listener container objects that I can initialize with closures to the protocol functions and thus work around the problem. That should work but I was wondering if there's a cleaner solution? Perhaps some way to type erasure away the generic requirement altogether?

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.

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.