2014-12-02 54 views
36

我在Swift中用下面的代码将我的头撞在墙上。我已经定义了一个简单的协议:不能分配给协议中的属性 - Swift编译器错误

protocol Nameable { 
    var name : String { get set } 
} 

,并实现与:

class NameableImpl : Nameable { 
    var name : String = "" 
} 

,然后我在另一个文件中的下列方法(不要问我为什么):

func nameNameable(nameable: Nameable, name: String) { 
    nameable.name = name 
} 

问题是编译器在此方法中为属性赋值给出以下错误:

不能分配到“可命名的”名字'

我看不到我在做什么错了...下面的代码编译好:

var nameable : Nameable = NameableImpl() 
nameable.name = "John" 

我肯定这是简单的我忽略了 - 我做错了什么?

回答

30

这是因为,名称是一个协议,斯威夫特不知道什么种类(味道)你的函数的传入命名是。它可能是一个类实例,当然 - 但它可能是一个结构实例。你不能分配到恒定结构的属性,如下面的例子说明:

struct NameableStruct : Nameable { 
    var name : String = "" 
} 
let ns = NameableStruct(name:"one") 
ns.name = "two" // can't assign 

那么,默认情况下,传入函数参数一个常数 - 这是完全一样的,如果你在您说nameable之前,在您的函数声明中说过let

解决的办法是把这个参数设置是一个常数:

func nameNameable(var nameable: Nameable, name: String) { 
        ^^^ 
+0

TL;博士变“让myProtocolConformingItem”到“变种myProtocolConformingItem” – 2015-05-06 21:06:54

+0

@马特虽然这个建议/解决方案肯定作品,目前甚至由编译器提出,你认为它是一种代码味道? – damirstuhec 2016-01-11 06:37:17

+0

我得到错误'使用未声明类型的可命名' – Jack 2017-08-04 14:17:01

76

@马特的前面回答是正确的。

另一种解决方案是将Nameable声明为class only protocol

protocol Nameable: class { 
//    ^^^^^^^ 
    var name : String { get set } 
} 

我觉得这个方案更适合这种情况。因为nameNameable是无用的,除非nameableclass的一个实例。

+0

我对Swift的欣赏只是因为这个而变得更大。 – 2015-05-05 09:46:03

+0

这个+10000。我遇到了一些实现协议和扩展的重大问题,这些协议和扩展涉及struct属性,并且无法在没有各种头痛的情况下进行变异,但添加'class'解决了所有问题。 – Mike 2015-10-02 01:37:48

+0

为什么这个工作,但不是'协议可命名的地方自我:UIView'(假设你只是想要继承这个协议的意见)。 UIView是一个类,但它不会真正摆脱他的错误。 – GoldenJoe 2017-11-15 06:59:21

0

在这里,我写了一些代码,这可能会给伴生泛型类型使用的一些想法:

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