Swift 枚举继承
Swift enum inheritance
你能继承Swift中的枚举吗?关于枚举继承,应该注意哪些规则?
以下测试代码:
enum TemperatureUnit: Int {
case Kelvin, Celcius, Farenheit
}
enum TemperatureSubunit : Temperature {
}
生成
error: type 'TemperatureSubunit' does not conform to protocol 'RawRepresentable'
在Swift语言中,我们有结构、枚举和类。 Struct 和 Enum 通过复制传递,但 类 通过引用传递。只有 类 支持继承,Enum 和 Struct 不支持。
所以要回答你的问题,你不能继承 Enum(和 Struct 类型)。看看这里:
Whosebug difference classes vs structs
正如 Korpel 已经回答的那样,目前不支持枚举的实际继承。所以不可能让某个枚举扩展和继承另一个枚举的情况。
但是,为了完成,我要补充一点,枚举确实支持协议,并且与 Swift 2 中引入的协议扩展和新的面向协议的编程方法(参见 this video)一起,它可以实现类似于继承的东西。这是我经常使用的一种技术,用于定义由枚举驱动的 UITableViewController
:s,指定 table 的部分以及每个部分中的行,并添加一些有用的行为。例如,请参见以下示例代码:
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
}
}
之前的代码将呈现以下内容 table:
注意如何通过实现协议,我们的 RegisterTableSection
枚举必须为协议中定义的方法和变量提供实现。最有趣的是,它通过 TableSection
协议扩展
继承了 变量 mandatoryTitle
的默认实现
我已经上传了这个例子的源码here
看我的例子,就简单多了:
详情
测试于:
- 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)
结果
你能继承Swift中的枚举吗?关于枚举继承,应该注意哪些规则?
以下测试代码:
enum TemperatureUnit: Int {
case Kelvin, Celcius, Farenheit
}
enum TemperatureSubunit : Temperature {
}
生成
error: type 'TemperatureSubunit' does not conform to protocol 'RawRepresentable'
在Swift语言中,我们有结构、枚举和类。 Struct 和 Enum 通过复制传递,但 类 通过引用传递。只有 类 支持继承,Enum 和 Struct 不支持。
所以要回答你的问题,你不能继承 Enum(和 Struct 类型)。看看这里:
Whosebug difference classes vs structs
正如 Korpel 已经回答的那样,目前不支持枚举的实际继承。所以不可能让某个枚举扩展和继承另一个枚举的情况。
但是,为了完成,我要补充一点,枚举确实支持协议,并且与 Swift 2 中引入的协议扩展和新的面向协议的编程方法(参见 this video)一起,它可以实现类似于继承的东西。这是我经常使用的一种技术,用于定义由枚举驱动的 UITableViewController
:s,指定 table 的部分以及每个部分中的行,并添加一些有用的行为。例如,请参见以下示例代码:
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
}
}
之前的代码将呈现以下内容 table:
注意如何通过实现协议,我们的 RegisterTableSection
枚举必须为协议中定义的方法和变量提供实现。最有趣的是,它通过 TableSection
协议扩展
mandatoryTitle
的默认实现
我已经上传了这个例子的源码here
看我的例子,就简单多了:
详情
测试于:
- 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)