扩展功能,扩展静态功能和扩展功能之间有什么区别? Swift中的扩展类函数?

时间:2018-01-29 21:57:15

标签: swift swift-extensions

我试图在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类型的参数

这是为什么?为什么将函数更改为静态函数或类函数会更改传递所需的类型?

提前致谢!

(非常感谢详细的答案)

2 个答案:

答案 0 :(得分:3)

请记住,UIColor是一个类。类有点像用于创建符合该类的实例或对象的蓝图。 UIColor.redUIColor类的实例的示例。

当您在类中定义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 个实例(即非staticclass)对您来说毫无用处,因为你还没有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.ColourCard.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方法几乎相同,只是classstatic之间的区别在于,您可以在子类中使用override class个方法。