我试图在UIColor上创建一个扩展函数,它可以使用Card.Colour类型的参数并将UIColor返回给调用者。
button.backgroundColor = UIColor.getColour(cardColour: cardToDeal.colour)
extension UIColor {
func getColour(cardColour: Card.Colour) -> UIColor {
switch cardColour {
case .Red:
return UIColor.red
case .Green:
return UIColor.green
case .Blue:
return UIColor.blue
}
}
}
当我尝试这样做时,UIColor.getColour的扩展功能要求我输入UIColor类型的参数,而不是扩展方法中指定的Card.Colour类型。
但是,当我将getColour的扩展函数更改为:
时static func getColour(cardColour: Card.Colour) -> UIColor {
class func getColour(cardColour: Card.Colour) -> UIColor {
它允许我传递Card.Colour类型的参数
这是为什么?为什么将函数更改为静态函数或类函数会更改传递所需的类型?
提前致谢!
(非常感谢详细的答案)
答案 0 :(得分:3)
请记住,UIColor
是一个类。类有点像用于创建符合该类的实例或对象的蓝图。 UIColor.red
是UIColor
类的实例的示例。
当您在类中定义func
时(在您的情况下,作为扩展名),Swift假定您要将func
添加到蓝图中,而蓝图将全部可用UIColor
类的实例,例如UIColor.red
。
您也可以在所有课程之外定义func
,只需将其放在模块的顶层,而不是放在extension
内。
但是,为了保持您的功能有条理,您可以将类似的功能放在类名中。您只需要告诉Swift您不会尝试将该函数添加到将应用于所有实例的蓝图中,而您想要的只是拥有一个名称为以类的名称为前缀。
以下是一个说明用法差异的示例:
class Test {
func notStatic() {
print("called from an instance")
}
static func thisIsStatic() {
print("called on class name directly")
}
}
let instance = Test() // this is an *instance* of Test
instance.notStatic() // we can call a non static func on instance
Test.thisIsStatic() // we can call a static func directly on the class only
现在,让我们回到你的具体例子一秒钟。请注意,在您的示例中,您从Card.Colour
的实例开始并尝试创建UIColor
的新实例。
换句话说,将func
添加到UIColor
个实例(即非static
或class
)对您来说毫无用处,因为你还没有UIColor
的实例。
创建类的新实例的惯用方法是使用初始化程序(init
)。因此,您可以将您的函数转换为UIColor上的初始化程序,如下所示:
extension UIColor {
convenience init(cardColour: Card.Colour) {
switch cardColour {
case .Red: self.init(cgColor: UIColor.red.cgColor)
case .Blue: self.init(cgColor: UIColor.blue.cgColor)
case .Green: self.init(cgColor: UIColor.green.cgColor)
}
}
}
现在,您只需致电UIColor(cardColour: .Red)
即可获得所需内容。请注意,在实施过程中,我将UIColor.red
转换为cgColor
并将其作为快速黑客进行转换。您可以在UIColor
的每个案例中Card.Colour
使用您认为合适的初始值设定项。
但还有另一种方式,我认为它更优雅。由于您已经拥有Card.Colour
的实例,因此可以使用为您提供与该实例对应的Card.Colour
的函数扩展UIColor
。在该函数中,您可以使用关键字Card.Colour
来引用self
实例。
由于您已经通过Card.Colour
拥有self
个实例,因此您无需将任何参数传递给该函数。这允许您使用一个名为计算属性的很酷的功能,以使用得更好。
这是您向Card.Colour
添加此类扩展程序的方式:
extension Card.Colour {
var uiColor: UIColor {
switch self {
case .Red: return .red
case .Blue: return .blue
case .Green: return .green
}
}
}
然后,您可以从UIColor
Card.Colour
或Card.Colour.Red.uiColor
获得mainColour.uiColor
,其中mainColour
的类型为Card.Colour
。
最后,正如Leo Dabus在评论中指出的那样,Swift's naming conventions是案例应该以小写字母开头。您应该使用Card.Colour.red
而不是Card.Colour.Red
等。这些约定是围绕Swift进行的。在此之前将案例名称大写是很常见的。
答案 1 :(得分:1)
扩展方法对提供的类型的实例进行操作。您可以在方法块内使用实例的所有internal
属性和方法。
static
方法是由类名命名的方法,不适用于类的任何特定实例。 class
方法几乎相同,只是class
和static
之间的区别在于,您可以在子类中使用override
class
个方法。