Dynamic invocation of instance methods in Swift

  • 2020-05-06 11:43:08
  • OfStack

There is an interesting way of writing Swift that instead of calling a method on this instance directly with an instance, we can take the signature of an instance method of that type by the type, and then pass the instance to get the actual method that needs to be called. Let's say we have this definition:


class MyClass {
    func method(number: Int) -> Int {
        return number + 1
    }
}

The most common way to use the method method is to generate an instance of MyClass and then call it:
with.method

let object = MyClass()
let result = object.method(1) // result = 2

This limits the ability to determine object instances and corresponding method calls only at compile time. In fact, we can rewrite the above example as
, using the method just mentioned

let f = MyClass.method
let object = MyClass()
let result = f(object)(1)

This syntax may seem strange, but it's not really complicated. In Swift, you can directly use the syntax of Type.instanceMethod to generate a method that can be coriolized. If we look at the type of f (Alt + click), we know that it is:

f: MyClass -> (Int) -> Int

In fact, for values like Type.instanceMethod, actually

let f = MyClass.method

What it does is a literal conversion like the following:

let f = { (obj: MyClass) in obj.method }

It is not hard to see why the above method can be called.

This method applies only to instance methods, and you cannot write getter or setter similarly for attributes. Also, if we encounter a name conflict with a type method:


class MyClass {
    func method(number: Int) -> Int {
        return number + 1
    }     class func method(number: Int) -> Int {
        return number
    }
}

If left unchanged, MyClass.method will take a type method, and if we want to take an instance method, we can explicitly add a type declaration to distinguish it. Not only does this work here, it works well in most other cases where the name is ambiguous:

let f1 = MyClass.method
// class func method The version of the let f2: Int -> Int = MyClass.method
// and f1 The same let f3: MyClass -> Int -> Int = MyClass.method
// func method The coriolized version of


Related articles: