【问题标题】:Unable to make a protocol for enum无法为枚举制定协议
【发布时间】:2019-12-10 21:40:59
【问题描述】:

我对协议不是很好,现在我很困惑。我正在尝试为具有name 属性(或需要的函数)的enum 制定协议。

这将允许我获取枚举值的名称,类似于单独遵守String,但首字母大写。例如,我想要发生的事情:

enum Furniture: Named {
    case table, chair, lamp
}

Furniture.table.name   // Returns 'Table'
Furniture.chair.name   // Returns 'Chair'
Furniture.lamp.name    // Returns 'Lamp'

这是我目前所拥有的:

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()
    }
}

这给了我错误,当我尝试更正它们时,会弹出另一个错误。

现在,这显示了以下错误:

类型“命名”被限制为非协议、非类类型“字符串”

“Self”类型的值没有成员“rawValue”

我该如何解决这个问题?

【问题讨论】:

  • String 上没有.capitalized() 吗?
  • @Alexander-ReinstateMonica 没意识到,谢谢!我从here 得到了那部分,前两个答案是使用这种方法(即使他们它是针对 Swift 5 的)。
  • 这对不能import Foundation的人来说会很好

标签: swift enums swift-protocols swift-extensions


【解决方案1】:

枚举通过RawRepresentable 协议获取它们的原始值,因此在限制扩展时应该使用它:

extension Named where Self: RawRepresentable, RawValue == String {
    var name: String {
        let str: String = self.rawValue
        return str.prefix(1).uppercased() + str.dropFirst()
    }
}

您还需要声明您的枚举使用String 作为其rawValue 的类型:

enum Furniture: String, Named {
    case table, chair, lamp
}

【讨论】:

  • 我认为不可能,但是有没有办法将enum Furniture: String, Named 折叠成enum Furniture: Named?或者以任何方式使rawValue 不可见(例如以某种方式使用private)?
【解决方案2】:

Furniture 枚举设置为字符串原始类型,Swift 编译器会自动添加 RawRepresentable 一致性。

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
    }
}

用于验证家具枚举的单元测试,

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")
    }
}

【讨论】:

    猜你喜欢
    • 2018-05-22
    • 2023-03-19
    • 1970-01-01
    • 1970-01-01
    • 2017-10-13
    • 2018-07-28
    • 2016-05-09
    • 2016-04-26
    • 1970-01-01
    相关资源
    最近更新 更多