Reputation: 30348
I have a particular pattern of using enums which are always of type String and which the enum (not its raw value) also adheres to a particular protocol. Written normally, this is like so...
private enum IndicatorA : String, IndicatorProtocol
{
case X
case Y
case Z
}
What I'm trying to do is to find out if there's anything I can do to make the string implied so all I have to type is this...
private enum IndicatorA : Indicator
{
case X
case Y
case Z
}
... where Indicator
dictates the raw value is of type String
and the enum itself also adheres to the IndicatorProtocol
protocol.
I've tried both of these to come up with something to use as the raw value's type, but neither compiles. Plus, technically that puts the protocol on the string, not the enum, so that isn't what I'm after anyway. (Again, I want the protocol on the enum, not the raw value.)
class Indicator : String, IndicatorProtocol
{
}
struct Indicator : String, IndicatorProtocol
{
}
So is there any way to do what I'm trying to achieve in either Swift 2.x or 3.x? Perhaps with constraints on the protocol somehow?
Upvotes: 1
Views: 462
Reputation: 13679
A couple thoughts on this:
Assuming it's possible to make the enum contain an Indicator
as its raw value, it's important to note that this would not actually make the enum itself conform to the IndicatorProtocol
, only its rawValue would conform. In other words:
enum IndicatorA : String, IndicatorProtocol
is not the same thing as:
enum IndicatorA : StringThatConformsToIndicatorProtocol
For the first example, you could access the protocol like this:
let example:IndicatorA = IndicatorA(rawValue:"Test")
example.someProtocolMethod()
For the second example, you would have to access the protocol like this:
let example:IndicatorA = IndicatorA(rawValue:"Test")
example.rawValue.someProtocolMethod()
because in the first example the enum itself is conforming to the protocol, but in the second example, the enum's raw value is conforming to the protocol.
All that said, you could sort of make the second example work by create an Indicator
struct that conforms to StringLiteralConvertible
, Equatable
and your own IndicatorProtocol
. Example:
protocol IndicatorProtocol {
func printHello()
}
struct Indicator: IndicatorProtocol, StringLiteralConvertible, Equatable {
let string: String
init(name value: String) {
self.string = value
}
init(stringLiteral value: String) {
self.string = value
}
init(extendedGraphemeClusterLiteral value: String) {
self.string = value
}
init(unicodeScalarLiteral value: String) {
self.string = value
}
func printHello() {
print("Hello from \(string)")
}
}
func ==(left:Indicator, right:Indicator) -> Bool {
return left.string == right.string
}
enum IndicatorA : Indicator {
case One = "One", Two = "Two"
}
let test = IndicatorA.One
print(test.rawValue.printHello()) // prints "Hello from One
But that's a good bit of extra work to achieve a result that is not what I think you were hoping for in the first place!
Upvotes: 1