Swift枚举继承


70

您可以在Swift中继承枚举吗?关于枚举继承,应注意哪些规则?

以下测试代码:

enum TemperatureUnit: Int {
    case Kelvin, Celcius, Farenheit
}

enum TemperatureSubunit : Temperature {  
}

产生

error: type 'TemperatureSubunit' does not conform to protocol 'RawRepresentable'

Answers:


79

在Swift语言中,我们有Structs,Enum和Classs。Struct和Enum通过副本传递,而类通过引用传递。只有类支持继承,而Enum和Struct不支持继承。

因此,要回答您的问题,您不能继承Enum(和Struct类型)。在这里看看:

stackOverflow差异类与结构


1
惊人的失败,但事实就是如此。感谢您提供信息。
Warpzit '16

72

正如Korpel已经回答的那样,当前Enums不支持实际的继承。因此,不可能有某个Enum扩展并继承另一个枚举的情况。

但是,我想补充一点,枚举确实支持协议,并结合Swift 2中引入的协议扩展和新的面向协议的编程方法(请参见本视频),可以实现类似于继承的东西。我经常使用这种技术来定义UITableViewController由枚举驱动的:s,以指定表的各节以及各节中的行,并添加一些有用的行为。例如,请参见以下示例代码:

import UIKit

protocol TableSection {
    static var rows: [Self] { get }

    var title: String { get }

    var mandatoryField: Bool { get }
}

extension TableSection {
    var mandatoryTitle: String {
        if mandatoryField {
            return "\(title)*"
        } else {
            return title
        }
    }
}

enum RegisterTableSection: Int, TableSection {
    case Username
    case Birthdate
    case Password
    case RepeatPassword

    static var rows: [RegisterTableSection] {
        return [.Username, .Password, .RepeatPassword]
    }

    var title: String {
        switch self {
        case .Username:
            return "Username"
        case .Birthdate:
            return "Date of birth"
        case .Password:
            return "Password"
        case .RepeatPassword:
            return "Repeat password"
        }
    }

    var mandatoryField: Bool {
        switch self {
        case .Username:
            return true
        case .Birthdate:
            return false
        case .Password:
            return true
        case .RepeatPassword:
            return true
        }
    }
}

class ViewController: UITableViewController {

    override func viewDidLoad() {
        super.viewDidLoad()
    }

    override func numberOfSectionsInTableView(tableView: UITableView) -> Int {
        return 1
    }

    override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return RegisterTableSection.rows.count
    }

    override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
        guard let row = RegisterTableSection(rawValue: indexPath.row) else {
            // This should never happen
            return UITableViewCell()
        }

        let cell = UITableViewCell()
        cell.textLabel?.text = row.mandatoryTitle
        return cell

    }
}

先前的代码将呈现下表:

枚举定义的表

注意,通过实现协议,我们的RegisterTableSection枚举必须如何为协议中定义的方法和变量提供实现。最有趣的是,它通过协议扩展继承了变量的默认实现mandatoryTitleTableSection

我已经在这里上传了此示例的源代码


1
这是一个很好的答案,它显示了面向协议编程的另一个好处
SomaMan

优秀的答案路易斯!
Korpel

47

看我的例子,它容易得多:一个枚举可以在Swift中包含另一个枚举值吗?

细节

经过测试:

  • Xcode 9.2,Swift 4和3
  • Xcode 10.2(10E125)和11.0(11A420a),Swift 5

enum State {
    case started
    case succeeded
    case failed
}

enum ActionState {
    case state(value: State)
    case cancelled
}

结果

ActionState枚举具有4个值:

.state(value: .started)
.state(value: .succeeded)
.state(value: .failed)
.cancelled

另一个样品

import Foundation

enum StringCharactersTransformType {
    case upperCase
    case lowerCase
}

enum StringTransformType {
    case state(value: StringCharactersTransformType)
    case normal

    static var upperCase: StringTransformType {
        return .state(value: .upperCase)
    }

    static var lowerCase: StringTransformType {
        return .state(value: .lowerCase)
    }
}

var type = StringTransformType.normal
print(type)
type = .upperCase
print(type)
type = .lowerCase
print(type)

结果

在此处输入图片说明 在此处输入图片说明


我喜欢。但是Enum的想法是您可以推断常量。像:someFunction("hello world",.upperCase) someFunction("hello world",.lowerCase)等等。这someFunction("hello world",.state(.upperCase))是不是很可读?好主意。
eonist

是的,你是对的。我已经编辑了答案(添加了漂亮代码的示例)。这样好点吗
瓦西里·博德纳丘克

但是,这是一种反向继承。这更像是构图。如果您考虑一下。在我看来,枚举在面向协议的编程中效果很好,而在OOP和继承中效果不佳。幸运的是,迅捷仍然支持OOP和POP。目前。
eonist

好点子!枚举组成!
努诺·贡萨尔维斯

是的,它实际上解决了无法扩展来自第三方框架的错误枚举的问题。构图正是我所需要的!
Segabond
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.