2014-12-02 38 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 
相關問題