How do I specify a typealias of a scene conforming to a specific protocol? - swift

I want to define a type which refers to only objects which are:
Members of a subclass of a given class
Conform to a specific protocol
How can I specify such a type? For instance, I'd like to be able to do something like this:
//Define a class
class MyClass {}
//Define a protocol
protocol MyProtocol {}
//Define an extension specific to this class and protocol
extension MyProtocol where Self : MyClass {}
//This works for multiple protocols, but not a class and a protocol
typealias MyAlias = MyClass & MyProtocol

Related

Can i pass protocol type to generic class

I have a protocol A and there are multiple structs conforming to protocol A. I need to store different struct objects in a collection. But my collection type is predefined by another service, which is of type - class Storage<Value:Codable>. I can't pass in Value type as A, and it throws an error saying Protocol A does not conform to type Decodable. I just want to know if this is a right approach passing a custom protocol and can i make a custom protocol conform to Codable Protocol. Sample code snippet.
Any thoughts would be helpful
class Storage<Value: Codable>{}
protocol A {}
struct Type1: A, Codable, Equatable, Comparable {}
struct Type2: A, Codable, Equatable, Comparable {}
let storage = Storage<A>() // Throws error - Type 'A' does not conform to protocol 'Decodable'
use basic class
class Storage<Value: Codable>{}
protocol A {}
class Type: A, Codable {}
class Type1: Type, Equatable, Comparable {}
class Type2: Type, Equatable, Comparable {}
let storage = Storage<Type>()

Multiple constraints on parameter of a generic function

Reading about generic functions in Swift, I see that it is possible to put some constraints on a parameter by requiring, that it is a subclass of a given class C, or that it implements a given protocol P.
But I wonder if there is a way to require both at the same time. I haven't found anything about that yet.
Does anyone know?
Actually You can do that.
If you have seen Codable in swift it is actually Decodable and Encodable
typealias Codable = Decodable & Encodable
So in some function if you are using generic T as Codable
struct StructOfCodable<T:Codable>: Codable {
....
}
Here is example
protocol Test {}
class TClass {
}
typealias Common = Test & TClass
func generic <T:Common>(method:T) {
}
Another way is protocol and class both can have super class. So you can create common protocol
like
protocol CommonInProtocolAndStruct { }
protocol ProtocolUsedAsConstraint:CommonInProtocolAndStruct {}
struct StructUsedAsConstraint:CommonInProtocolAndStruct {}
And any method you can use CommonInProtocolAndStruct as generic constraint
You can add any number of type constraints using a where clause. Examples:
import UIKit
func f<T>(t: T) where T: UIView, T: Encodable {}
class C<T> where T: UIView, T: Encodable {}

Can a protocol require conforming types to be a subtype of another type?

For example: I'd like to say in a protocol definition that, a class conforming it, needs to also subclass UIView or another custom class type MyClass. Is that possible?
Yes you can, just define your protocol as:
protocol SomeProtocol where Self: MyClass {
// protocol code here
}

Swift 4 - Subclass Generic Constraint from associatedtype

I'd like to write a Swift protocol that requires a type to specify a base class and implement methods that operate on subclasses of that base class. Here's what that might look like (doesn't compile):
protocol Repository {
associatedtype BaseModel
//T must subclass BaseModel
func all<T: BaseModel>(from type: T.Type) -> [T]
}
But this generates the following compiler error:
Inheritance from non-protocol, non-class type 'Self.BaseModel'
This makes sense, because BaseModel could be specified with a struct type and subclassing wouldn't be allowed. So I tried creating an empty protocol, constrained to classes, to try to inform the compiler that this type will be a class type and allow a subclass constraint.
protocol Model: class { }
Then I constrained the BaseModel type using the Model class protocol:
associatedtype BaseModel: Model
But this generates the same compiler error from above. Is it possible to enforce a subclass constraint from an associatedtype on a protocol? I would expect the above to compile or for Swift to allow something like the following to allow subclass constraints:
associatedtype BaseModel: class
Associated Types should be used when type is unknown before the protocol is implemented. But if type is known no need to use associated type. I guess you could do this.
protocol Model: class { }
class BaseModel : Model { }
protocol Repository {
func all<T : BaseModel>(from type: T.Type) -> [T]
}

Further constraining a generic function from a Swift Protocol

I have a Swift protocol defined like this:
protocol MyProtocol {
func genericMethod<T:MyProtocol>(param:T) -> ()
}
I can implement the generic method in a base class like this:
class MyBaseClass : MyProtocol {
func genericMethod<T where T:MyProtocol>(param:T) -> () {
println("Performing generic method for type \(T.self)")
}
}
class MySubClass : MyBaseClass {
...
}
So far, so good. I can implement this method and it compiles and runs just fine.
Now, I want to do something similar but in my base class I want to further constrain the type of the generic method by requiring it to conform with a protocol such as Comparable. I try this:
class MyBaseClass : MyProtocol {
func genericMethod<T where T:MyProtocol, T:Comparable>(param:T) -> () {
println("Performing generic method for type \(T.self)")
}
}
Once I add this additional constraint on type T, the class MyClass will not compile because it does not conform to the protocol anymore.
It seems like adding an additional constraint on a generic type should not cause it to cease conforming with a protocol. What am I missing? It seems to me that the protocol is saying that genericMethod must be passed a parameter of a type that conforms with MyProtocol. When I go to implement this in MyBaseClass - just one possible implementation of MyProtocol - that I should be able to restrict that implementation further by saying that the parameter myst conform with Comparable in addition to MyProtocol
Is there a way to refine a generic type in a base implementation like I'm trying to do here?
Adding the additional constraint on a generic type should cause it to cease conforming with the protocol because the protocol is supposed to guarantee conformance, and conformance cannot be guaranteed with subtypes that aren't Comparable. If you want all MyProtocol objects to conform to Comparable then you should make it part of the MyProtocol definition.
protocol MyProtocol: Comparable {
//...
}
I haven't tried this, but it might also work if you make MyBaseClass a Comparable type.
One solution is to go the other way - define your protocol's version of the generic as the most restrictive case. This compiles:
protocol P {
func genericMethod<T where T:P, T:Comparable>(param:T) -> ()
}
class C1 : P {
func genericMethod<T> (param:T) -> () {} // compiles even though omits Comparable
func test() {
genericMethod(C1()) // compiles even though C1 is not a Comparable
}
}