我有一个具有以下语法的函数:
func myfunc<V1,V2>(to: (V1)->V2, from: (V2)->V1)
并且如您所见,我为此功能提供了2个闭包。 这2个闭包用于将V1
转换为V2
,反之亦然。请记住,我不能以extension
到V1
或V2
的形式提供这些转换。我想提高函数的可用性,我想知道什么是更常见的更好的提供方法这两个是Swift用户。
尽管我有3种方法,每种方法各有优缺点。
第一种方法:使用当前语法。
func myfunc<V1,V2>(to: (V1)->V2, from: (V2)->V1)
优点:用户提供2个闭包,因此他可以更好地组织代码。此外,他可以就地提供它们。
缺点:函数调用将变长,并且只能使用trailing closure
进行第二次关闭。
第二种方法:对两者都使用一个闭包,并通过一个参数对其进行区分。
enum ConvertClosure {
case .to(Any)
case .from(Any)
}
func myfunc<V1,V2>(operation: (ConvertClosure)->Any)
优点:函数调用变得更加简单,我们也可以使用trailing closure
。
缺点: 2个关闭的责任现在都在一个,所以变得更加复杂。无法添加泛型检查,需要使用Any
作为枚举大小写参数和函数的返回类型。
第三种方法:使用协议而不是闭包。
protocol ConvertOperation {
associatedtype InVal
associatedtype OutVal
func to(_ val: InVal) -> OutVal
func from(_ val: OutVal) -> InVal
}
func myfunc<V1,V2>(operation: ConvertOperation)
where ConvertOperation.InVal == V1, ConvertOperation.OutVal == V2
优点:函数调用变得更加简单。我们从泛型进行类型检查。
缺点:我们需要遵守无法就地完成的协议。方法不是使用闭包,因此可能不是很迅速。
哪种方法更适合Swift用户?您能提出更好的方法吗?
答案 0 :(得分:2)
这可能是基于观点的,但一般规则是:
请使用最具体的类型。您希望类型在编译期间为您捕获错误。
要重用功能时,请使用协议。协议将要求您使用将实现它的结构/类,因此使其更难使用。因此,当您已经有一个符合该协议的对象或功能被重用时,它会更好,因此您可以创建一个对象并多次使用它。
要对您的案件发表更多评论:
如果存在多个闭包参数,则不应使用结尾的闭包,因为这会影响可读性。但是,这不是一个不好的解决方案,而且很常见。
这通常是一个不好的解决方案,因为它使用Any
类型,它违反了上面的规则1。始终尽量减少使用Any
。大多数应用程序都不应该使用它。
这不是一个不好的解决方案,但是请参见规则2。仅在特定使用情况下,我才是最佳选择。
还要考虑NSObject
与Any
基本相同。通常,应避免在Swift代码中使用它,因为基本上是在类型检查时辞职。
另请注意,您不应以代码尽可能短为目标。始终以可读性为目标。
在不知道确切用例的情况下,我们可能无法给出更具体的建议。