Swift: 符合协议声明 class 函数返回实例
Swift: Conform to protocol declaring class function returning instance
我想要一个通用协议,用于返回给定 class 的新“随机”配置实例。
在 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: ...)
}
}
但是无论我如何配置它都会抛出错误。
我如何正确地为 class 方法返回符合 classes 的实例制定协议?
你的问题是因为 return 从 randomExample
变成 UIColor
,因为 randomExample
希望你 return 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
覆盖,MyColor
调用的 randomExample
将尝试 return 一个 UIColor
。但是,randomExample
期望 return 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 and 。
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()
我想要一个通用协议,用于返回给定 class 的新“随机”配置实例。
在 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: ...)
}
}
但是无论我如何配置它都会抛出错误。
我如何正确地为 class 方法返回符合 classes 的实例制定协议?
你的问题是因为 return 从 randomExample
变成 UIColor
,因为 randomExample
希望你 return 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
覆盖,MyColor
调用的 randomExample
将尝试 return 一个 UIColor
。但是,randomExample
期望 return 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 and
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()