[英]Defining a Swift Protocol for Arbitrary, Int-based Enums
I have this enumeration representing a color, and I have added several methods to conveniently obtain new instances based on arithmetic operations on the original's raw value: 我有一个代表颜色的枚举,并且添加了几种方法,可以根据对原始原始值的算术运算方便地获取新实例:
enum Color : Int
{
case Red = 0
case Green
case Blue
case Cyan
case Magenta
case Yellow
static func random() -> Color
{
return Color(rawValue: Int(arc4random_uniform(6)))!
}
func shifted(by offset:Int) -> Color
{
return Color(rawValue: (self.rawValue + offset) % 6)!
// Cyclic: wraps around
}
}
(This harks back to the old enums being just int constants) (这回想起只是int常量的旧枚举)
The problem is, I have several other int-based enums where I would like to introduce similar functionality, but without duplicating code. 问题是,我还有其他几个基于int的枚举,我想在其中引入类似的功能,但又不重复代码。
I think I should define a protocol extension on RawRepresentable
where RawValue == Int
: 我认为我应该在
RawRepresentable
上定义协议扩展,其中RawValue == Int
:
extension RawRepresentable where RawValue == Int
{
...but that's where my understanding of the syntax ends. ...但这就是我对语法的理解的终点。
Ideally, I would like to require a static method returning the number of cases, and a provide default implementation of both random()
and shifted(_:)
above that takes that into account (instead of the hard-coded 6 here). 理想情况下,我想要求使用静态方法返回案例数,并提供对
random()
和shifted(_:)
默认实现,并将其考虑在内(而不是此处的硬编码6)。
CONCLUSION: I have accepted the answer by Zoff Dino . 结论:我已经接受了佐夫·迪诺的回答 。 Even though the answer given by Rob Napier is exactly what I asked for, it turns out what I was asking for was not the most elegant design after all, and the other answer suggests a better approach.
即使Rob Napier给出的答案恰好是我所要求的,但事实证明,我所要求的毕竟不是最优雅的设计,而其他答案则建议了一种更好的方法。 Still, I have upvoted both answers;
不过,我对两个答案都赞成。 thanks everyone.
感谢大家。
You're almost there. 你快到了。 You just need Nate Cook's case-counting code from https://stackoverflow.com/a/27094913/97337 .
您只需要来自https://stackoverflow.com/a/27094913/97337的 Nate Cook的案件计数代码。
extension RawRepresentable where RawValue == Int {
// See http://natecook.com/blog/2014/10/loopy-random-enum-ideas/
static var caseCount: Int {
var max: Int = 0
while let _ = self.init(rawValue: ++max) {}
return max
}
static func random() -> Self {
return Self(rawValue: Int(arc4random_uniform(UInt32(caseCount))))!
}
func shifted(by offset:Int) -> Self {
return Self(rawValue: (self.rawValue + offset) % self.dynamicType.caseCount)!
// Cyclic: wraps around
}
}
You should extend your custom protocol instead of RawRepresentable
. 您应该扩展自定义协议,而不是
RawRepresentable
。 Try this: 尝试这个:
protocol MyProtocol {
static var maxRawValue : Int { get }
static func random() -> Self
func shifted(by offset: Int) -> Self
}
enum Color : Int, MyProtocol
{
case Red = 0
case Green
case Blue
case Cyan
case Magenta
case Yellow
// The maximum value of your Int enum
static var maxRawValue: Int {
return Yellow.rawValue
}
}
extension MyProtocol where Self: RawRepresentable, Self.RawValue == Int {
static func random() -> Self {
let random = Int(arc4random_uniform(UInt32(Self.maxRawValue + 1)))
return Self(rawValue: random)!
}
func shifted(by offset: Int) -> Self {
return Self(rawValue: (self.rawValue + offset) % (Self.maxRawValue + 1))!
}
}
let x = Color.random()
let y = x.shifted(by: 1)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.