[英]Can I use a generic return type without having to downcast?
I have 2 different types of credential objects in my code. 我的代码中有2种不同类型的凭据对象。
What I'm trying to do is use a generic function to construct and return the correct object based on Object.TYPE 我正在尝试使用通用函数来构造并基于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
. 我的代码似乎可以正常工作,但是在实现中,我需要使用forced downcast
。
I also had to create a "dummy protocol
" for my 2 different credentials which also seems "wrong" 我还必须为我的2个不同的凭证创建一个"dummy protocol
”,这似乎也是“错误的”
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)
You can't use your specific class without downcasting. 您不能使用您的特定班级,而无需垂头丧气。 But there is another issue. 但是还有另一个问题。
Your code seems like a template method implementation with smething missing. 您的代码似乎像是缺少一些东西的模板方法实现。 Your dummy interface
. 您的虚拟interface
。
I think, you shuold ask this question yourself: What makes CredentialsIA
and OCredential
same, What is their common point. 我想,您shuold自己问了这个问题: CredentialsIA
和OCredential
相同,它们的共同点是什么? And use this in your interface. 并在您的界面中使用它。 If you can do it, you can use your interface to perform tasks without need to know what their exact type are. 如果可以做到,则可以使用界面执行任务,而无需知道其确切类型。 Otherwise, you need downcasting. 否则,您需要向下转换。
Exaple: 的exaple:
protocol C{
func myCommonPointFunc() -> Something
}
class CredentialsIA: C{
func myCommonPointFunc() -> Something{
//implementation
}
}
class OCredential: C{
func myCommonPointFunc() -> Something{
//implementation
}
}
Usage: 用法:
let credentialsA: Credentials = Credentials.CredentialsIA(apiKey: kAPIKey, apiSecret: kAPISecret)
var result = creadentailsA.credential().myCommonPoinFunc()
Also, this method prevents you to pass your class type to your enum
's credential()
method. 此外,此方法还防止您将类类型传递给enum
的credential()
方法。 You can even use factory classes
that implement a factory interface
instead of an enum
您甚至可以使用实现factory interface
而不是enum
factory classes
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.