@dynamicCallable與callAsFunction(將型別例項作為函式呼叫)
阿新 • • 發佈:2021-06-22
@dynamicCallable與callAsFunction都是可以通過型別例項作為函式呼叫的實現方法。
@dynamicCallable實現方式,將此屬性應用於類、結構、列舉或協議,以將該型別的例項視為可呼叫函式,你必須實現dynamicallyCall(withArguments:)
或dynamicallyCall(withKeywordArguments:)其中一個或兩個方法,如下:
@dynamicCallable struct Adder{ func dynamicallyCall(withArguments args: [Int]) -> Int{return args.reduce(0) {$0+$1} } func dynamicallyCall(withArguments args: [Float]) -> Float{ return args.reduce(0) {$0+$1} } func dynamicallyCall(withKeywordArguments pairs: KeyValuePairs<String, Int>) -> Int{ return pairs.map {$1}.reduce(0){$0+$1}; } }
func runTest() -> Void{ let add = Adder() print("add: \(add(1, 2, 3, 4, 5))") print("add: \(add(1.2, 2.4, 3.6, 4.8, 5.8))") print("add: \(add(a: 1, b: 2, c: 3, d: 4, e: 5))") }
// 輸出如下: // add: 15 // add: 17.8 // add: 15
callAsFunction實現方式,你只需要實現名字為callAsFunction的方法即可,引數和返回值自己任意定義,如下:
struct OtherAdder { func callAsFunction(_ a: Int, _ b: Int) -> Int{ return a + b } func callAsFunction(_ a: Float, _ b: Float) -> Float{ return a + b } func callAsFunction(str1: String, str2: String, a: Int, b: Int) -> String{ return "\(str1)+\(str2)=\(a+b)" } } func runTest() -> Void{ let add = OtherAdder() print("add: \(add(1, 2))") print("add: \(add(1.5, 1.5))") print("add: \(add(str1: "1", str2: "2", a: 1, b: 2))") } // 輸出如下: // add: 3 // add: 3.0 // add: 1+2=3
從上面兩個demo可以看出兩者的區別,總結如下:
1、@dynamicCallable實現的方法呼叫,引數型別必須一致;callAsFunction引數型別可以不一致
2、@dynamicCallable必須實現方法名為dynamicallyCall引數標籤名稱必須為withArguments或withKeywordArguments的方法;callAsFunction必須實現方法名callAsFunction但引數標籤可以自定義的方法
從上可以看出,callAsFunction實現的引數標籤命名更加靈活
相同點:兩者實現的方法都支援方法過載,但@dynamicCallable過載方法的引數標籤必須為withArguments或withKeywordArguments