Alex
Alex

Reputation: 551

How to cast generic T to conform to protocol

I need to cast the generic type in a class to conform to a protocol. I can not use constraints since the container class has to be serialized. So how could i cast in this case the T to ZNumeric when i allready know (i can check as you see) that it conforms to the protocol?

//: Playground - noun: a place where people can play

import UIKit

protocol ZNumeric {

}

extension Double: ZNumeric {

}

class GenericClass<T> {

}

class RestrictedGenericClass<T:ZNumeric> {

}

class Container {
    required init?<T>(type: T.Type) {
        let a = GenericClass<T>()
        print(a)

        if T.self is ZNumeric.Type {
            print("is numeric")
            //let b = RestrictedGenericClass<T>() // Will not work obviously
            //print(b)
        }
    }
}

let cDouble = Container(type: Double.self) // if T.self is ZNumeric.Type is true
let cString = Container(type: String.self) // if T.self is ZNumeric.Type is false

Upvotes: 2

Views: 974

Answers (2)

TopChul
TopChul

Reputation: 459

I think you looking for this.

protocol ZNumeric {

}

extension Double: ZNumeric {

}

class GenericClass<T> {

}

class RestrictedGenericClass<T:ZNumeric> {

}

class Container<T> {
    required init?(value: T) {
    }
    convenience init?(_ value: T) {
        self.init(value: value)
        let a = GenericClass<T>()
        print(a)
    }
}
extension Container where T: ZNumeric {
    convenience init?(_ value: T) {
        self.init(value: value)
        let b = RestrictedGenericClass<T>() // Will not work obviously
        print(b)
    }
}

print("test Double")
let cDouble = Container(1.1) // if T.self is ZNumeric.Type is true
print("test String")
let cString = Container("") // if T.self is ZNumeric.Type is false

// test Double
// RestrictedGenericClass<Swift.Double>
// test String
// GenericClass<Swift.String>
  1. make internal Required Initializer
  2. make initializer for T: AnyObject
  3. make initializer for T: ZNumeric

Upvotes: 0

Kametrixom
Kametrixom

Reputation: 14993

Because generics have to be known at compile-time, you cannot just check at run-time for conformance (I'm pretty sure). I think this is more like what you want:

class Container {
    required init?<T>(type: T.Type) {
        let a = GenericClass<T>()
        print(a)
    }

    required init?<T : ZNumeric>(type: T.Type) {
        let a = GenericClass<T>()
        print(a)

        print("is numeric")
        let b = RestrictedGenericClass<T>()
        print(b)
    }
}

The more specific initialiser will be chosen at compile-time.

Upvotes: 2

Related Questions