mercredi 30 janvier 2019

Can I use a generic return type without having to downcast?

I have 2 different types of credential objects in my code.

What I'm trying to do is use a generic function to construct and return the correct object based on Object.TYPE

So essentially I want to change the return type and the construction based on whatever condition.

My code seems to be working but in my implementation I need to use a forced downcast.

I also had to create a "dummy protocol" for my 2 different credentials which also seems "wrong"

This makes me suspicious that Im going about it the wrong way.

How can I do this without downcasting?

public protocol C {    
}

// Generic Creation method

public enum Credentials {
    case CredentialsIA(apiKey: String, apiSecret: String)
    case CredentialsO(username: String, secret: String, ipsName: String)
    func crendential<T:C>( type: T.Type) -> T {
        switch self {
        case .CredentialsIA(let apiKey, let apiSecret):
            return IACredentials(kAPIKey: apiKey, kAPISecret: apiSecret) as! T
        case .CredentialsO(let username, let secret, let ipsName):
              return OCredential(kUsername: username, kAPIKey: secret, kIPSName: ipsName) as! T
        }
    }
}

Credential Types

public struct IACredentials: C {
    public let kAPIKey: String
    public let kAPISecret: String
    public init(kAPIKey: String, kAPISecret: String) {
        self.kAPIKey = kAPIKey
        self.kAPISecret = kAPISecret
    }
}
public struct OCredential: C {
    public let kUsername: String
    public let kAPIKey: String
    public let kIPSName: String
    public init(kUsername: String, kAPIKey: String, kIPSName: String ) {
        self.kUsername = kUsername
        self.kAPIKey = kAPIKey
        self.kIPSName = kIPSName
    }
}

Instantiation

let credentialsA: Credentials = Credentials.CredentialsIA(apiKey: kAPIKey, apiSecret: kAPISecret)

let credentialsB : Credentials = Credentials.MIPCredentialsOriient(username: "sds", secret: "sdsd", ipsName: "sssd")

Usage after init

 let credential:IACredentials = credentialsA.crendential(type: IACredentials.self)

Aucun commentaire:

Enregistrer un commentaire