Reputation: 30341
I am not very good with protocols, and I'm quite stuck right now. I am trying to make a protocol for an enum
, which has a name
property (or function if it needs to be).
This will allow me to get the name of an enum value, similar to conforming to String
alone, but with the first letter capitalised instead. For example, what I want to happen:
enum Furniture: Named {
case table, chair, lamp
}
Furniture.table.name // Returns 'Table'
Furniture.chair.name // Returns 'Chair'
Furniture.lamp.name // Returns 'Lamp'
Here is what I have so far:
protocol Named {
var name: String { get }
}
extension Named where Named: String {
var name: String {
let str: String = self.rawValue
return str.prefix(1).uppercased() + str.dropFirst()
}
}
This gives me errors, and when I try to correct them, another error pops up.
Right now, this shows me the following errors:
Type 'Named' constrained to non-protocol, non-class type 'String'
Value of type 'Self' has no member 'rawValue'
How can I fix this?
Upvotes: 1
Views: 2265
Reputation: 9915
Set the Furniture
enum to a string raw type, the Swift compiler automatically adds RawRepresentable conformance.
protocol Named {
var name: String { get }
}
enum Furniture: String, Named {
case table, chair, lamp
}
extension Named where Self: RawRepresentable, RawValue == String {
var name: String {
return rawValue.capitalized
}
}
A Unit Tests to validate the Furniture enum,
import XCTest
class FurnitureTests: XCTestCase {
func testEnumDisplayNameFirstLetterCapitlized() {
XCTAssertEqual(Furniture.table.name, "Table")
XCTAssertEqual(Furniture.chair.name, "Chair")
XCTAssertEqual(Furniture.lamp.name, "Lamp")
}
func testEnumRawValue() {
XCTAssertEqual(Furniture.table.rawValue, "table")
XCTAssertEqual(Furniture.chair.rawValue, "chair")
XCTAssertEqual(Furniture.lamp.rawValue, "lamp")
}
}
Upvotes: 0
Reputation: 9825
Enums get their raw value via the RawRepresentable
protocol, so that's what you should use when constraining your extension:
extension Named where Self: RawRepresentable, RawValue == String {
var name: String {
let str: String = self.rawValue
return str.prefix(1).uppercased() + str.dropFirst()
}
}
You also need to declare that your enum uses a String
as the type of its rawValue
:
enum Furniture: String, Named {
case table, chair, lamp
}
Upvotes: 4