我在Swift中使用以下代码将头撞到墙上。我已经定义了一个简单的协议:
protocol Nameable {
var name : String { get set }
}
并通过以下方式实现:
class NameableImpl : Nameable {
var name : String = ""
}
然后我在另一个文件中有以下方法(不要问我为什么):
func nameNameable( nameable: Nameable, name: String ) {
nameable.name = name
}
问题是编译器在此方法中为属性赋值提供了以下错误:
无法分配到' name'在&name;'
我无法看到我做错了什么......以下代码编译得很好:
var nameable : Nameable = NameableImpl()
nameable.name = "John"
我确定这件事情我已经被忽视了 - 我做错了什么?
答案 0 :(得分:90)
@ matt's anwer是正确的。
另一种解决方案是将Nameable
声明为class
only protocol。
protocol Nameable: class {
// ^^^^^^^
var name : String { get set }
}
我认为,这种解决方案更适合这种情况。由于nameNameable
是nameable
的实例,因此class
无效。
答案 1 :(得分:36)
这是因为,Nameable是一个协议,Swift不知道你的函数的Nameable是什么的种(风味)。它可能是一个类实例,当然 - 但它可能是一个struct实例。并且无法分配给常量struct 的属性,如下例所示:
struct NameableStruct : Nameable {
var name : String = ""
}
let ns = NameableStruct(name:"one")
ns.name = "two" // can't assign
嗯,默认情况下,传入的函数参数是一个常量 - 就像你在说let
之前在函数声明中说过nameable
一样。< / p>
解决方案是使此参数不成为常量:
func nameNameable(var nameable: Nameable, name: String ) {
^^^
注意更高版本的Swift取消了var
函数参数表示法,因此您可以通过将常量赋值给变量来完成相同的操作:
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
}
答案 2 :(得分: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