我很好奇为什么这行不通:
.btn-update {
color:#004990;
background-color: #F58020;
}
.btn-update:hover {
background-color: #F8AA69;
color: #3E5485
}
.btn-delete {
color:#F58020;
background-color:#004990;
}
.btn-delete:hover {
background-color: #3E5485;
color: #F8AA69;
}
.test{
color: #FF0000;
}
错误:
无法分配给属性:“自身”是不可变的
为什么?只有类可以采用MyProtocol2。如果我在MyProtocol后面添加public protocol MyProtocol {
var i: Int { get set }
}
public protocol MyProtocol2: class, MyProtocol {}
public extension MyProtocol2 where Self: AnyObject {
func a() {
i = 0 <-- error
}
}
声明,它将起作用。我不明白为什么它在子协议上不起作用。
答案 0 :(得分:9)
您的示例无法编译,因为MyProtocol
不受类限制,因此可以具有mutating
要求和扩展成员。这包括属性设置器,默认情况下为mutating
。这样的成员可以自由地为self
重新分配一个全新值,这意味着编译器需要确保在可变变量上调用它们。
例如,考虑:
public protocol MyProtocol {
init()
var i: Int { get set } // implicitly `{ get mutating set }`
}
extension MyProtocol {
var i: Int {
get { return 0 }
// implicitly `mutating set`
set { self = type(of: self).init() } // assign a completely new instance to `self`.
}
}
public protocol MyProtocol2 : class, MyProtocol {}
public extension MyProtocol2 where Self : AnyObject {
func a() {
i = 0 // error: Cannot assign to property: 'self' is immutable
}
}
final class C : MyProtocol2 {
init() {}
}
let c = C()
c.a()
如果这是合法的,则调用c.a()
会将C
的全新实例重新分配给变量c
。但是c
是不可变的,因此代码格式不正确。
使MyProtocol
类绑定(即protocol MyProtocol : AnyObject
或不赞成使用的拼写protocol MyProtocol : class
)起作用是因为现在编译器知道只有类可以符合MyProtocol
。因此,它通过禁止mutating
要求和扩展成员来强加引用语义,从而防止self
的任何变异。
可供您使用的另一种选择是将需求i
的设置者标记为nonmutating
–因此,这意味着只能由不变的设置者来满足。这使您的代码再次格式正确:
public protocol MyProtocol {
init()
var i: Int { get nonmutating set }
}
public protocol MyProtocol2 : class, MyProtocol {}
public extension MyProtocol2 where Self : AnyObject {
func a() {
i = 0 // legal
}
}
答案 1 :(得分:0)
属性设置器会在被调用方上触发突变,这意味着对属性进行操作的任何方法都必须声明为mutating
:
public extension MyProtocol2 where Self: AnyObject {
mutating func a() {
i = 0
}
}
这将允许在方法中对self
进行任何写操作。