@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
要得到你必须要付出,要付出你还要学会坚持,如果你真的觉得很难,那你就放弃,但是你放弃了就不要抱怨,我觉得人生就是这样,世界真的是平等的,每个人都要通过自己的努力,去决定自己生活的样子。