1. 程式人生 > 其它 >@dynamicCallable與callAsFunction(將型別例項作為函式呼叫)

@dynamicCallable與callAsFunction(將型別例項作為函式呼叫)

@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