Reputation: 644
I'm banging my head against the wall with the following code in Swift. I've defined a simple protocol:
protocol Nameable {
var name : String { get set }
}
and implemented that with:
class NameableImpl : Nameable {
var name : String = ""
}
and then I have the following method in another file (don't ask me why):
func nameNameable( nameable: Nameable, name: String ) {
nameable.name = name
}
The problem is that the compiler gives the following error for the property assignment in this method:
cannot assign to 'name' in 'nameable'
I can't see what I'm doing wrong... The following code compiles fine:
var nameable : Nameable = NameableImpl()
nameable.name = "John"
I'm sure it's something simple I've overlooked - what am I doing wrong?
Upvotes: 55
Views: 15230
Reputation: 534950
It's because, Nameable being a protocol, Swift doesn't know what kind (flavor) of object your function's incoming Nameable is. It might be a class instance, sure - but it might be a struct instance. And you can't assign to a property of a constant struct, as the following example demonstrates:
struct NameableStruct : Nameable {
var name : String = ""
}
let ns = NameableStruct(name:"one")
ns.name = "two" // can't assign
Well, by default, an incoming function parameter is a constant - it is exactly as if you had said let
in your function declaration before you said nameable
.
The solution is to make this parameter not be a constant:
func nameNameable(var nameable: Nameable, name: String ) {
^^^
NOTE Later versions of Swift have abolished the var
function parameter notation, so you'd accomplish the same thing by assigning the constant to a variable:
protocol Nameable {
var name : String { get set }
}
func nameNameable(nameable: Nameable, name: String) {
var nameable = nameable // can't compile without this line
nameable.name = name
}
Upvotes: 46
Reputation: 549
Here, i written some code, that might give some idea on Associated generic type Usage:
protocol NumaricType
{
typealias elementType
func plus(lhs : elementType, _ rhs : elementType) -> elementType
func minus(lhs : elementType, _ rhs : elementType) -> elementType
}
struct Arthamatic :NumaricType {
func addMethod(element1 :Int, element2 :Int) -> Int {
return plus(element1, element2)
}
func minusMethod(ele1 :Int, ele2 :Int) -> Int {
return minus(ele1, ele2)
}
typealias elementType = Int
func plus(lhs: elementType, _ rhs: elementType) -> elementType {
return lhs + rhs
}
func minus(lhs: elementType, _ rhs: elementType) -> elementType {
return lhs - rhs
}
}
**Output:**
let obj = Arthamatic().addMethod(34, element2: 45) // 79
Upvotes: 0
Reputation: 51911
@matt's anwer is correct.
Another solution is to declare Nameable
as a class
only protocol.
protocol Nameable: class {
// ^^^^^^^
var name : String { get set }
}
I think, this solution is more suitable for this case. Because nameNameable
is useless unless nameable
is a instance of class
.
Upvotes: 117