George
George

Reputation: 30341

Unable to make a protocol for enum

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

Answers (2)

Blazej SLEBODA
Blazej SLEBODA

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

dan
dan

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

Related Questions