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.