Collectives™ on Stack Overflow

Find centralized, trusted content and collaborate around the technologies you use most.

Learn more about Collectives

Teams

Q&A for work

Connect and share knowledge within a single location that is structured and easy to search.

Learn more about Teams

This would be nice to have, as the resulting signature of the protocol is satisfied by adding the defaulted parameter. Is there any way to get this to work with Swift 2?

This is a simplified example. Let's say, for the sake of argument, that the protocol is fixed. A solution can only update the Messager class. My goal is to be able to call sendMessage() like so:

let m: Messaging = Messager()
m.sendMessage("")

The only way I found to accomplish this (and satisfy the compiler) is with overloading like so:

class Messager: Messaging {
    func sendMessage(message: String) {
        self.sendMessage(message, count: 1)
    func sendMessage(message: String, count: Int = 1) {}

The problem with this approach is that my defaults are then specified in two places and I lose the main advantage of Swift's default parameters.

in Swift 3 you could use extensions to solve that, however it's a bit ugly. Hope for a better solution in next swift versions.

import UIKit
protocol TestProtocol {
    func testFunction(a: Int, b: Int?) -> String
extension TestProtocol
    func testFunction(a: Int, b: Int? = nil) -> String {
        return testFunction(a: a, b: b)
class TestClass: TestProtocol
    func testFunction(a: Int, b: Int?) -> String {
        return "a: \(a), b: \(b)"
func testit(testProtocol: TestProtocol) {
    print(testProtocol.testFunction(a: 10)) // will print a: 10, b: nil
    print(testProtocol.testFunction(a:10, b:20)) // will print a: 10, b: Optional(20)
let t = TestClass()
testit(testProtocol: t)

However, this would somehow lead to one issue. If some class is not conforming to the protocol, it wont result in a compile error but rather in an endless loop.

A slightly better solution (in my opinion) is to capsulate the default parameter in a second function like this:

import Foundation
protocol TestProtocol {
    func testFunction(a: Int, b: Int?) -> String
extension TestProtocol
    // omit the second parameter here
    func testFunction(a: Int) -> String {
        return testFunction(a: a, b: nil) // <-- and use the default parameter here
class TestClass: TestProtocol
   func testFunction(a: Int, b: Int?) -> String 
       return "testFunction(a: \(a), b: \(b))"       
func testit(testProtocol: TestProtocol) {
    print(testProtocol.testFunction(a: 10)) // will print a: 10, b: nil
    print(testProtocol.testFunction(a: 10, b: 20)) // will print a: 10, b: Optional(20)
print(Date())
let t = TestClass()
testit(testProtocol: t)

In this way the compiler will notify when a class does not conform to the protocol, and also wont end up in and endless loop.

This won't work if protocol is written in objective-c (i.e. declared using @objc) since it dosen't support optional chaining. – Jayprakash Dubey Sep 15, 2020 at 8:37

If anyone is still looking for an answer to this, this link helped me out:

https://oleb.net/blog/2016/05/default-arguments-in-protocols/

Basically the original function definition includes all the params you need:

protocol Messaging {
    func sendMessage(message: String, count: Int)

and your extension provides the default values, calling your original protocol function with those default values:

extension Messaging {
    func sendMessage(message: String, count: Int = 1) {
        sendMessage(message, count)
                If you make count optional in the protocol function like I did, the endless loop is not only in your head ... ;-)
– TheEye
                Aug 22, 2017 at 17:09
                @TheEye I don't see your answer code here. Do you mean you're the author of the post?! Still, from what I understand it seems that this doesn't call the function in the extension...rather it calls the function in the original protocol. I just don't understand why/how it does that!
– mfaani
                Sep 21, 2017 at 19:18
                @Honey "this doesn't call the function in the extension" – correct, well at least not directly (w/ static dispatch), that is. When you call a method on a protocol-typed instance (in this example, the method is being implicitly called on self, which is typed as Messaging), if that method is a protocol requirement (such as in this case), it will be dispatched dynamically via the protocol witness table for the underlying conforming type of the instance. In the case where the type provides its own implementation of the requirement; that implementation will be called. So no infinite loop.
– Hamish
                Sep 21, 2017 at 19:43
                Although that being said, if the conforming type had not provided its own implementation, there would be an infinite loop, as the extension would then be dispatched to. This is a fairly serious issue with this solution, and was avoided in the linked blog post by using a different name for the extension method (so that it doesn't satisfy the requirement as a default implementation).
– Hamish
                Sep 21, 2017 at 19:43

With Swift 2 you can now extend your protocol like so and give it a default implementation

protocol Messageable {
    func sendMessage(message: String)
extension Messageable {
    func sendMessage(message: String, count: Int = 1) {
        // Do your default implementation

I am still learning about this so I am not 100% sure how this will work with your send message example, but I believe this is what you are looking for.

There are so many new cool things you can do with protocols in Swift 2.

Watch Apple's presentation which is very good:

https://developer.apple.com/videos/play/wwdc2015-408/

and read these:

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

I don't think it addresses what I'm trying to achieve. A protocol extension would only help me if the protocol could define default arguments, which it can't. – Dov Jan 6, 2016 at 16:57 yeah thats what I just thought in your specific example. I just updated my answer to reflect this. Not possible to adjust your protocol to make it more generic? – crashoverride777 Jan 6, 2016 at 17:00 No, I'd like the protocol to contain the minimum number of arguments. The updated protocol extension you gave just shifts the implementation with defaults from a specific instance, to cover all instances. I'd still need to define the method twice. – Dov Jan 6, 2016 at 17:03 you can override the extension by implementing the 2 methods in your scenes. Thats why I thought might be relevant. You have a general implementation in the extension and if you need a specific one you just define the method in the scene which will override the extension. – crashoverride777 Jan 6, 2016 at 22:08 In my case protocol method are in objective-c (i.e. declared with @objc) so above mentioned solution dosen't work. – Jayprakash Dubey Sep 15, 2020 at 8:33

You could add typealiases to your protocol to represent possible different argument types in your protocol-blueprinted function .sendMessage. In the example below I have explicitly specified that the 2nd argument has neither an internal nor an external name.

Since you have two typealiases, you can either implement this blueprint as one using two different types (Messenger in example below), or, simply throw away the second argument (AnotherMessenger in example) as an empty tuple type () with default value () (you can think of this as a void type with a value of void).

protocol Messaging {
    typealias T
    typealias U
    func sendMessage(message: T, _ _ : U)
/* Class where you make use of 2nd argument */
class Messager: Messaging {
    func sendMessage(message: String, _ count: Int) {
        print(message + "\(count)")
/* Class where you ignore 2nd argument */
class AnotherMessager : Messaging {
    func sendMessage(message: String, _ _ : () = ()) {
        print(message)
/* Tests */
var a = Messager()
a.sendMessage("Hello world #", 1)
// prints "Hello World #1"
var b = AnotherMessager()
b.sendMessage("Hello world")
// prints "Hello World"

This is as close as I can get you to simulate the behaviour you describe in the question and in the comments below. I'll leave the alternative solutions below in case they can help someone else with similar thought but less hard design constraints.

Another option: not exactly the behaviour your asking for, but you could use an anonymous closure as the single parameter to your protocol-blueprinted function, where this close take no arguments but returns an array of Any objects, which you can access and treat in your sendMessage function as you wish.

protocol Messaging {
    func sendMessage(@autoclosure messages: ()->[Any])
class Messager: Messaging {
    func sendMessage(@autoclosure messages: ()->[Any]) {
        for message in messages() {
            print(message, terminator: "")
var a = Messager()
a.sendMessage([String("Hello "), String("World "), String("Number "), Int(1)])
// prints "Hello World Number 1"

Another alternative would be to have to separate blueprints of function sendMessage(..) in your protocol Messaging, one with and one without the additional parameter count. You thereafter add default (dummy) implementations for both of these functions via extension of protocol Messaging. Your class Messager will then comply to Messaging protocol even without any implementation of sendMessage(..) in it at all; in the lack thereof, the default implementations are used. Finally make a detailed implementation only the sendMessage function you wish to use in your class.

protocol Messaging {
    func sendMessage(message: String)
    func sendMessage(message: String, count: Int)
/* Extend blueprints with default dummy implementations */
extension Messaging {
    func sendMessage(message: String) { }
    func sendMessage(message: String, count: Int = 1) { }
class Messager: Messaging {
    func sendMessage(message: String, count: Int = 1) {
        print(message + "\(count)")
var a = Messager()
a.sendMessage("Hello world #")
// prints "Hello World #1"

Note however that instances of your class will list both sendMessage functions as available class methods; one of them being your function, and the other the dummy default implementation.

Old answer prior to edit regarding different type parameters (I'll leave it here as it can be a possible alternative in the case where all parameters are of same type)

Finally, you could make use of variadic parameters:

protocol Messaging {
    func sendMessage(messages: String...)
class Messager: Messaging {
    func sendMessage(messages: String...) {
        for message in messages {
            print(message)
var a = Messager()
a.sendMessage("Hello", "World", "!")
  

A variadic parameter accepts zero or more values of a specified type. You use a variadic parameter to specify that the parameter can be passed a varying number of input values when the function is called. Write variadic parameters by inserting three period characters (...) after the parameter’s type name.

I updated my question to reflect that the example I gave is simplified. It's not just concatenating strings. There are a variety of parameter types. – Dov Jan 5, 2016 at 0:03 @Dov Ok, then the above is, naturally, not applicable. I'll see if I can come up with alternative, or if someone else can help you first. – dfrib Jan 5, 2016 at 0:04 Interesting approach, but then the protocol isn't really serving much of a purpose. Can you think of a method that wouldn't require the protocol to change? – Dov Jan 5, 2016 at 0:15 @Dov Just a comment: I'd say protocol many times serves purposes just as this: you could write a generic function with protocol Messaging as a type constraint. You would then know that all generic types conforming to that constraint will have access to a function sendMessage (with the specific function signature). See e.g. stackoverflow.com/questions/34475597/… for an interesting example. Anyway, back to the question: I'll see if I can give this a third try, or if I'll strike out on this last one. – dfrib Jan 5, 2016 at 0:19 @Dov: I can't come up with any way (except for the workarounds in my answer) to come around the fact that by a class conforming to a protocol, it's expected to contain implementation for all protocol blueprints, with the exception of those blueprints that have default implementations (via extension MyProtocol ...). In your example above, the addition of the default valued count parameter ascertains that class Messenger does no longer conform to your protocol. Are you sure this is a behaviour you're really looking for, or could you perhaps use an alternative approach? – dfrib Jan 5, 2016 at 0:31

Thanks for contributing an answer to Stack Overflow!

  • Please be sure to answer the question. Provide details and share your research!

But avoid

  • Asking for help, clarification, or responding to other answers.
  • Making statements based on opinion; back them up with references or personal experience.

To learn more, see our tips on writing great answers.