如果你有这样的协议:
protocol Messaging {
func sendMessage(message: String)
}
有什么办法可以满足它在这样一个类中:
class Messager: Messaging {
func sendMessage(message: String, count: Int = 1) {}
}
这将是一个很好的选择,因为通过添加默认参数可以满足协议的签名结果。有什么方法可以让它在Swift 2中工作吗?
这是一个简化的例子。为了便于讨论,我们假设协议是固定的。解决方案只能更新Messager类。我的目标是能够像这样调用sendMessage()
:
let m: Messaging = Messager()
m.sendMessage("")
我发现实现这一点(并使编译器满意)的唯一方法是使用如下重载:
class Messager: Messaging {
func sendMessage(message: String) {
self.sendMessage(message, count: 1)
}
func sendMessage(message: String, count: Int = 1) {}
}
这种方法的问题是,我的默认值在两个地方指定,我失去了Swift默认参数的主要优势。
4条答案
按热度按时间pvcm50d11#
在Swift 3中,你可以使用扩展来解决这个问题,但是它有点难看。希望在下一个Swift版本中有更好的解决方案。
然而,这会导致一个问题,如果某个类不符合协议,它不会导致编译错误,而是导致无限循环。
一个稍微好一点的解决方案(在我看来)是将默认参数封装在第二个函数中,如下所示:
通过这种方式,编译器将在类不符合协议时发出通知,并且也不会以无限循环结束。
sirbozc52#
如果有人还在寻找这个问题的答案,这个链接帮了我的忙:
https://oleb.net/blog/2016/05/default-arguments-in-protocols/
基本上,原始函数定义包括您需要的所有参数:
并且您的扩展提供了默认值,则使用这些默认值调用原始协议函数:
1l5u6lss3#
使用Swift 2,您现在可以像这样扩展您的协议,并为其给予一个默认实现
我还在学习这方面的知识,所以我不能100%确定这将如何与您的发送消息的例子,但我相信这是你正在寻找的。
在Swift 2中,你可以用协议做很多新的酷事情。
观看Apple的演示,非常精彩:
https://developer.apple.com/videos/play/wwdc2015-408/
并阅读以下内容:
http://matthijshollemans.com/2015/07/22/mixins-and-traits-in-swift-2/
http://code.tutsplus.com/tutorials/protocol-oriented-programming-in-swift-2--cms-24979
http://www.raywenderlich.com/109156/introducing-protocol-oriented-programming-in-swift-2
pkln4tw64#
您可以在协议中添加类型别名,以表示协议蓝图函数
.sendMessage
中可能存在的不同参数类型。在下面的示例中,我明确指定了第二个参数既没有内部名称,也没有外部名称。由于您有两个类型别名,因此您可以使用两个不同的类型(下面的示例中为
Messenger
)将此蓝图实现为一个蓝图,或者,只需将第二个参数(下面的示例中为AnotherMessenger
)丢弃为一个空元组类型()
,默认值为()
(您可以将其视为一个void类型,值为void)。这是我能让你模拟你在问题和下面的评论中描述的行为的最接近的方法。我将在下面留下替代的解决方案,以防它们能帮助其他有类似想法但设计约束不那么严格的人。
另一个选项:这并不完全符合您的要求,但您可以使用匿名闭包作为protocol-blueprinted函数的单个参数,其中该闭包不接受任何参数,但返回一个
Any
对象数组,您可以在sendMessage
函数中访问和处理这些对象。另一种选择是必须在您的协议
Messaging
中分离函数sendMessage(..)
的蓝图,一个带有附加参数count
,另一个不带有附加参数count
。此后,您可以添加默认通过扩展X1 M10 N1 X协议实现这些功能的 * 两者 *。您的类Messager
将遵循Messaging
协议,即使其中根本没有任何sendMessage(..)
的实现;最后,只对您希望在类中使用的sendMessage
函数进行详细的实现。但是请注意,类的示例将把
sendMessage
函数都列为可用的类方法;其中一个是您的函数,另一个是伪默认实现。最后,您可以使用variadic parameters:
可变参数接受零个或多个指定类型的值。使用可变参数可以指定在调用函数时可以向该参数传递不同数量的输入值。通过在参数的类型名称后插入三个句点字符(...)来编写可变参数。