What I want to do is somewhat complicated, pardon all the variable names.
Currently I have been to doing something like
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
}
This is causing me to duplicate a LOT of code though. Because the same functions can (for the most part) be run on either Grunt1
or Grunt2
, and I keep having to specify with something like this
protocol Bletch {
func doSomething(to grunt: Grunt1)
func doSomething(to grunt: Grunt2)
}
But the implementations are the same for both functions. This is quite frustrating. I'd like to do something like
protocol Fum {
associatedType Thud
var zot: Thud { get set }
}
struct Grunt<T: Foo>: Fum {
typealias Thud = T
}
This would then let me do something like
let grunt1 = Grunt<Foo.Bar>(zot: .prop11) //Autocompletes to .prop11, .prop12, .prop13
let grunt2 = Grunt<Foo.Baz>(zot: .prop23) //Autocompletes to .prop23, .prop22, .prop23
Then I could do something like
protocol Bletch {
func doSomething(to grunt: Fum) // or (any Fum), whichever doesn't throw errors.
}
But this doesn't work, Is there a different way of getting the result I'm after? I'm just trying to reduce duplicate code.
Most of what you describe already works except <T: Foo>
since Foo
is not a protocol.
Instead of making Foo.Bar
and Foo.Baz
nested types, you can make Foo
a protocol and let both Bar
and Baz
adopt the protocol. (why are they nested types anyways?):
protocol Foo {}
enum Bar : Foo { /* cases */ }
enum Baz : Foo { /* cases */ }
If that's not an option, you can also extend Foo.Bar
and Foo.Baz
and let them both adopt to a common protocol:
protocol FooProtocol {}
extension Foo.Bar : FooProtocol {}
extension Foo.Baz : FooProtocol {}
Now you just need to constraint your generic T
on Grunt
to be a FooProtocol
instead of Foo
:
struct Grunt<T: FooProtocol>: Fum {
typealias Thud = T
var zot: Thud
}