How to construct generic without protocol in Swift? - swift

I'm getting the following error...
'T' cannot be constructed because it has no accessible initializers
When compiling...
class Sub<T : Equitable> {
func def(v : T) -> Bool{
var d = T() // <- Error
return d == v
}
}
var s = Sub<Int>()
println(s.def(0), s.def(1)) // I'm expecting "true, false"
I understand that in order for a generic type to be initialized, it needs to conform to a protocol that contains an init() constructor. Such as...
protocol A : Equitable {
init()
}
class Sub<T : A> {
But then I would get get the error
Type 'Int' does not conform to protocol 'A'
at the line
var s = Sub<Int>()
So how would I go about making a value type such as Int or Bool conform to a protocol that can be initialized?

You need to extend Int like so for it to adopt protocol A:
class Sub<T : A> {
func def(v : T) -> Bool{
var d = T()
return d == v
}
}
protocol A : Equatable {
init()
}
extension Int: A {
}
var s = Sub<Int>()
s.def(0) // true
s.def(1)) // false

Related

Heterogeneous array that conforms to protocol with associated type in Swift

I have a protocol AProtocol with an associated type AType and a function aFunc. I want to extend Array such that it conforms to the protocol by using the result of its elements aFunc function. Clearly this is only possible if elements of the array conform to Aprotocol and have the same associated type so I have set this toy example:
protocol AProtocol {
associatedtype AType
func aFunc(parameter:AType) -> Bool
}
extension Array : AProtocol where Element : AProtocol, Element.AType == Int {
func aFunc(parameter: Int) -> Bool {
return self.reduce(true, { r,e in r || e.aFunc(parameter: parameter) })
}
}
extension String : AProtocol {
func aFunc(parameter: Int) -> Bool {
return true
}
}
extension Int : AProtocol {
func aFunc(parameter: Int) -> Bool {
return false
}
}
This works fine for arrays which contain only one type:
let array1 = [1,2,4]
array1.aFunc(parameter: 3)
However for heterogeneous arrays, I get the error Heterogeneous collection literal could only be inferred to '[Any]'; add explicit type annotation if this is intentional and then Value of type '[Any]' has no member 'aFunc' if annotate it as follows:
let array2 = [1,2,"Hi"] as [Any]
array2.aFunc(parameter: 3)
Is it possible to extend Array as I wish such that heterogeneous arrays are allowed so long as they conform to AProtocol and have the same AType?
See if this fits your needs.
Approach:
Remove the associated type
Implementation:
protocol BProtocol {
func aFunc(parameter: BProtocol) -> Bool
}
extension String : BProtocol {
func aFunc(parameter: BProtocol) -> Bool {
return true
}
}
extension Int : BProtocol {
func aFunc(parameter: BProtocol) -> Bool {
return false
}
}
extension Array : BProtocol where Element == BProtocol {
func aFunc(parameter: BProtocol) -> Bool {
return self.reduce(true, { r,e in r || e.aFunc(parameter: parameter) })
}
}
Invoking:
let a1 : [BProtocol] = [1, 2, 3, "Hi"]
let boolean = a1.aFunc(parameter: 1)

Not Able to access values with .Type swift

Why am I not able to assign and read value from Type B in below code? B.self should be passed as a type and not an instance, so it should access static var in class B right?
class A{
}
class B:A{
static var a = 5
}
class c{
static func a(){
b(type: B.self)
}
static func b(type:B.Type){
print(type.a)
}
func takeObject<T>(type:T.Type){
print(type(of:String.self)) // String.Type
print(type) // B
print(type.a) // Value of type 'T' has no member 'a'
var a :type // Use of undeclared type 'type'
}
}
let objects : c = c()
objects.takeObject(object: B.self)
Correct me please, I am new on this topic and it seems quite interesting.
As i think you just want to add objects of type B so you can specify generic T of type B as below,
class A {}
class B: A {
static var a = 5
}
class c {
static func a() {
b(type: B.self)
}
static func b(type: B.Type){
print(type.a)
}
func takeObject<T: B>(type: T.Type){
print(type)
print(type.a)
var a : T
}
}
let objects : c = c()
objects.takeObject(type: B.self)

Swift Associated type constraints

I have two protocols with each defining an associated type. One of the protocols needs to define a variable of typed the other protocol where they both have the same type for associated type. Is it possible to somehow infer the type of associated type?
protocol A {
associatedtype AModel
var b: B { get }
}
protocol B {
associatedtype BModel
func doAnother(anotherModel: BModel)
}
Here is what I tried with no success
protocol A {
associatedtype AModel
associatedtype TypedB = B where B.BModel == AModel
var another: TypedB { get }
}
protocol B {
associatedtype BModel
func doAnother(anotherModel: BModel)
}
Please find the following working playground example. You need to use the associated type's name, not the constraining protocol's name. The reason for this is described here.
import Foundation
protocol A {
associatedtype AModel
associatedtype TypedB: B where TypedB.BModel == AModel
var another: TypedB { get }
}
protocol B {
associatedtype BModel
func doAnother(anotherModel: BModel)
}
// compiles
struct One: B {
typealias BModel = String
func doAnother(anotherModel: String) {}
}
struct Second: A {
typealias AModel = String
typealias TypedB = One
var another: One
}
// does not compile
struct Third: B {
typealias BModel = Int
func doAnother(anotherModel: Int) {}
}
struct Fourth: A { // A' requires the types 'Fourth.AModel' (aka 'String') and 'Third.BModel' (aka 'Int') be equivalent
typealias AModel = String
typealias TypedB = Third
var another: Third
}

Nested generics in a swift function

Assume I have this bit of code:
protocol MyProtocol {
}
struct MyStruct: MyProtocol {
}
class MyClass<P: MyProtocol> {
// Required for compiling
required init() {
}
}
class MySpecialClass: MyClass<MyStruct> {
}
func foo<P: MyProtocol, C: MyClass<P>>(protocolType: P.Type) -> C {
return C()
}
This compiles and calling
let specialClass: MySpecialClass = foo(protocolType: MyStruct.self)
creates an instance of type MySpecialClass.
What I would like is to not have to pass in the type of P so that I could simply call
let specialClass: MySpecialClass = foo()
and P would be automatically deduced.
Is there any way to make this happen?
As #Hamish already mentioned,
func foo<P, C: MyClass<P>>() -> C {
return C()
}
let specialClass: MySpecialClass = foo()
works in Swift 4. The Swift 3 compiler however complains that
error: generic parameter 'P' is not used in function signature
and a possible workaround is to add a dummy parameter of type
P? with a default value:
func foo<P, C: MyClass<P>>(dummy: P? = nil) -> C {
return C()
}
let specialClass: MySpecialClass = foo()
I believe that this will work:
protocol MyProtocol {
}
struct MyStruct: MyProtocol {
}
class MyClass<P: MyProtocol> {
// added a typealias for P
typealias ContainedProtocol = P
// Required for compiling
required init() {
}
}
class MySpecialClass: MyClass<MyStruct> {
}
// added a default value for protocolType
func foo<P, C: MyClass<P>>(protocolType: P.Type = C.ContainedProtocol.self) -> C {
return C()
}
let specialClass: MySpecialClass = foo()
By adding a typealias for P in MyClass<P: MyProtocol> we can refer to that type. We then set it as a default value in foo<P, C: MyClass<P>>(protocolType:) -> C. The compiler can then deduce P from that information.
Martin R’s version seems to work about as well as mine so go with whichever you like best. His seems a bit cleaner as it doesn’t need a typealias and it is fairly succinct.
Here’s his (it was a comment, it’s now an answer):
func foo<P, C: MyClass<P>>(dummy: P? = nil) -> C { ... }

In Swift, How do I use an associatedtype in a Generic Class where the type parameter is constrained by the protocol?

In Swift, I've got a protocol like this:
protocol P {
associatedtype T
func f(val:T)
}
I want to define a class like this:
class B<X:P> {
}
And then use the associatedtype T within the class B.
I've tried this:
class B<X:P> {
var v:T // compiler says "Use of undeclared type"
init() {
}
}
I've also tried this:
class B<X:P, Y> {
typealias T = Y
var v:T
init() {
}
func g(val:X) {
val.f(val: v) // compiler says "Cannot invoke 'f' with an argument list of type '(val:Y)'
}
}
Any suggestions?
T is the associated type of the placeholder type X, so you reference it as X.T. Example:
class B<X: P> {
var v: X.T
init(v: X.T) {
self.v = v
}
func g(x: X) {
x.f(val: v)
}
}