有一种方法来获得通用约束采取在枚举swift?或者有没有更好的方法来减少代码?



我想做的事情有点复杂,请原谅所有的变量名。

目前我一直在做一些像

enum Foo {
enum Bar {
case prop11
case prop12
case prop13
// etc
}
enum Baz {
case prop21
case prop22
case prop23
// etc
}
}
protocol Fum1 {
var zot: Foo.Bar { get set }
}
protocol Fum2 {
var zot: Foo.Baz { get set }
}
struct Grunt1: Fum1 {
// code
}
struct Grunt2: Fum2 {
// code
}

这导致我复制了很多代码。因为相同的函数可以(在大多数情况下)在Grunt1Grunt2上运行,并且我必须一直使用这样的东西来指定

protocol Bletch {
func doSomething(to grunt: Grunt1)
func doSomething(to grunt: Grunt2)
}

但是这两个函数的实现是相同的。这很令人沮丧。我想做一些像

protocol Fum {
associatedType Thud
var zot: Thud { get set }
}
struct Grunt<T: Foo>: Fum {
typealias Thud = T
}

接下来我要做的是

let grunt1 = Grunt<Foo.Bar>(zot: .prop11) //Autocompletes to .prop11, .prop12, .prop13
let grunt2 = Grunt<Foo.Baz>(zot: .prop23) //Autocompletes to .prop23, .prop22, .prop23

然后我可以这样写

protocol Bletch {
func doSomething(to grunt: Fum) // or (any Fum), whichever doesn't throw errors.
}

但是这不起作用,有没有别的方法可以得到我想要的结果?我只是想减少重复的代码。

你所描述的大部分已经工作,除了<T: Foo>,因为Foo不是一个协议。

不让Foo.BarFoo.Baz嵌套类型,可以让Foo成为一个协议,让BarBaz都采用该协议。(为什么它们是嵌套类型呢?):

protocol Foo {}
enum Bar : Foo { /* cases */ }
enum Baz : Foo { /* cases */ }

如果这不是一个选项,你也可以扩展Foo.BarFoo.Baz,让它们都采用一个共同的协议:

protocol FooProtocol {}
extension Foo.Bar : FooProtocol {}
extension Foo.Baz : FooProtocol {}

现在你只需要将Grunt上的通用T约束为FooProtocol而不是Foo:

struct Grunt<T: FooProtocol>: Fum {
typealias Thud = T
var zot: Thud
}

最新更新