在ObjC中:
@protocol Random
+ (instancetype)random;
@end
@interface UIColor (Random)
<Random>
@end
@implementation
+ (instancetype)random {
return [UIColor colorWith...];
}
@end
它适用于ObjC,但我无法在Swift中使用它。
在Swift中:
protocol Random {
static func randomExample() -> Self
}
extension UIColor: Random {
final class func randomExample() -> UIColor {
return UIColor(red: ...)
}
}
但无论我如何配置它都会引发错误。
答案 0 :(得分:4)
您的问题源于尝试从UIColor
返回randomExample
,因为randomExample
希望您返回Self
。
采取以下不正确的示例:
// Here `Self` is `UIColor`.
extension UIColor: Random {
class func randomExample() -> Self {
return UIColor(...) // Here's the problem...
}
}
// Here `Self` is `MyColor`.
class MyColor: UIColor {}
由于randomExample
未覆盖MyColor
,randomExample
调用的MyColor
会尝试返回UIColor
。但是,randomExample
期望返回MyColor
个实例。
要解决此问题,您可以:
extension UIColor: Random {
class func randomExample() -> Self {
// `self` refers to the current class.
// If this wasn't a class method you would use `self.dynamicType`
return self(red: 0, green: 0, blue: 0, alpha: 0)
}
}
let color1 = UIColor.randomExample() // color1 is a `UIColor`.
let color2 = MyColor.randomExample() // color2 is a `MyColor`.
如果您使用的是Swift 2,则需要使用:
self.init(red: 0, green: 0, blue: 0, alpha: 0)
您可能也有兴趣:Protocol func returning Self和Implementing NSCopying in Swift with subclasses。
答案 1 :(得分:4)
ABakerSmith值得回答您的问题,但我想扩展他的答案,以显示相同的协议如何适用于Struct和Enum的值类型。由于无法从中派生值类型,因此它们的协议实现只使用类型名称而不是Self。
编辑:按要求添加代码。
protocol Random {
static func random() -> Self
}
extension Float: Random {
static func random() -> Float {
return Float(arc4random()) / Float(UInt32.max)
}
}
extension CGFloat: Random {
static func random() -> CGFloat {
return CGFloat(Float.random())
}
}
extension UIColor: Random {
static func random() -> Self {
return self.init(
red: CGFloat.random(),
green: CGFloat.random(),
blue: CGFloat.random(),
alpha: 1.0)
}
}
let c1 = UIColor.random()
let c2 = UIColor.random()
let c3 = UIColor.random()