@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

 

 

posted @ 2021-06-22 17:00  zbblogs  阅读(263)  评论(0编辑  收藏  举报