我正在尝试编写一个用于拆分测试的函数,该函数在传递枚举值时以通用响应进行响应。
在下面的代码中,当调用 getSplit(forFeature:)
函数时,SplitResponse
根据传入的 Feature
而变化。
protocol SplitResponse {
associatedtype T
func split() -> T
}
enum Feature {
case feature1 // split test = Feature1Split
case feature2 // split test = Bool
}
enum Feature1Split {
case splitA
case splitB
case splitC
}
func getSplit(forFeature: Feature) -> SplitResponse {
switch feature {
case .feature1: return Feature1Response()
case .feature2: return Feature2Response()
}
}
struct Feature1Response: SplitResponse {
typealias SplitResponse = Feature1Split
func getSplit() -> SplitResponse {
// split logic
return .splitA
}
}
struct Feature2Response: SplitResponse {
typealias SplitResponse = Bool
func getSplit() -> SplitResponse {
// split logic
return true
}
}
let split1 = getSplit(forFeature: .feature1).split()
switch split1 {
case .splitA: // doSomething
case .splitB: // doSomethingElse
case .splitC: // doAnotherThing
}
let split2 = getSplit(forFeature: .feature2).split()
if split2 == true {
// doSomething
} else {
// doSomethingElse
}
但是,我在 getSplit(forFeature:)
of Protocol 'SplitResponse' can only be used as a generic constraint because it has Self or associated type requirements
第一季度。我相信解决方案是根据传入的 SplitResponse
关联 Feature
类型。我该怎么做?
第 2 季度。有没有办法完全摆脱 Feature1Response
、Feature2Response
结构和 SplitResponse
协议?那么 getSplit(forFeature:)
直接返回 Feature1Split
或 Bool 吗?
答案 0 :(得分:0)
不能如你所愿。您需要使用更多枚举。
extension Feature {
enum Split {
case feature1(Feature1Split)
case feature2(Bool)
}
var split: Split {
switch self {
case .feature1:
return .feature1(.splitA)
case .feature2:
return .feature2(true)
}
}
}
此语言没有像您可能希望的那样使用 split
的出色工具,此后。查看我的回答 here,了解您需要做的事情,以帮助您解决问题,如果您需要进一步的指导,请告诉我。
答案 1 :(得分:0)
您可以使用枚举:
enum Feature {
case feature1 // split test = Feature1Split
case feature2 // split test = Bool
}
enum Feature1Split {
case splitA
case splitB
case splitC
}
enum SplitResponse {
case feature1Response(value:Feature1Split)
case feature2Response(value:Bool)
}
func getSplit(forFeature feature: Feature) -> SplitResponse {
switch feature {
case .feature1: return .feature1Response(value: .splitA) // or some other split logic
case .feature2: return .feature2Response(value: true) // or some other split logic
}
}
let split1 = getSplit(forFeature: .feature1)
if case .feature1Response(let value) = split1 {
switch value {
case .splitA: print ("splitA")
case .splitB: print ("splitB")
case .splitC: print ("splitC")
}
} else {
print ("Ooops - Did not expect other than feature1Response")
}
let split2 = getSplit(forFeature: .feature2)
if case .feature2Response(let value) = split2 {
if (value) {
print ("feature2 response is true")
} else {
print ("feature2 response is false")
}
} else {
print ("Ooops - Did not expect other than feature2Response")
}
答案 2 :(得分:0)
Swift 目前不支持您尝试执行的操作。让我们看看这一行:
let split1 = getSplit(forFeature: .feature1).split()
它返回 SplitResponse
对象,但它只是一个没有具体 associatedtype
的纯协议对象。因此,当您调用您的 split
(在您的 strut
对象中是 getSplit,可能是那里的拼写错误?)函数时,编译器没有机会检测到返回类型是什么。 Swift 编译器不喜欢那样,这就是您遇到的错误。
即使您的两个对象符合相同的协议,也没有有意义的方式将它们一起使用。例如,让我们考虑这种情况:
let split1 = getSplit(forFeature: .feature1).split()
let split2 = getSplit(forFeature: .feature2).split()
print(split1 == split2)
print(split1 == split2)
表达式将无效,因为编译器无法真正知道 split1
和 split2
是什么类型。一个可以是 Bool
另一个 Feature1Split
类型,这会使表达式无效。另一方面,两者都可以是 Bool
,这将使表达式有效。但即使我们知道这是有效的,编译器也没有机会知道这一点。
答案 3 :(得分:0)
如果您不介意可选项,您也可以尝试使用类型擦除的 AnyResponse
:
protocol SplitResponse {
associatedtype T
func split() -> T
}
struct AnyResponse {
private struct Box<T> {
let split: () -> T
}
private let box: Any
init<Response: SplitResponse>(_ response: Response) {
box = Box(split: response.split)
}
func split<T>() -> T? {
guard let box = box as? Box<T> else {
return nil
}
return box.split()
}
}
enum Feature {
case feature1 // split test = Feature1Split
case feature2 // split test = Bool
}
enum Feature1Split {
case splitA
case splitB
case splitC
}
func getSplit(forFeature feature: Feature) -> AnyResponse {
switch feature {
case .feature1: return AnyResponse(Feature1Response())
case .feature2: return AnyResponse(Feature2Response())
}
}
struct Feature1Response: SplitResponse {
func split() -> Feature1Split {
// split logic
return .splitA
}
}
struct Feature2Response: SplitResponse {
func split() -> Bool {
// split logic
return true
}
}
let split1: Feature1Split? = getSplit(forFeature: .feature1).split()
switch split1 {
case .splitA:
print("doSomething")
case .splitB:
print("doSomethingElse")
case .splitC:
print("doAnotherThing")
case .none:
print("nil")
}
let split2: Bool? = getSplit(forFeature: .feature2).split()
if split2 == true {
print("doSomething")
} else {
print("doSomethingElse")
}