Cannot assign to property in protocol - Swift compiler error

IosSwift

Ios Problem Overview


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?

Ios Solutions


Solution 1 - Ios

@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.

Solution 2 - Ios

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
}

Solution 3 - Ios

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

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionolensmarView Question on Stackoverflow
Solution 1 - IosrintaroView Answer on Stackoverflow
Solution 2 - IosmattView Answer on Stackoverflow
Solution 3 - IosNarendra GView Answer on Stackoverflow