Swift 无法分配给类型为的不可变表达式。。。但是有协议

Swift 无法分配给类型为的不可变表达式。。。但是有协议,swift,protocols,Swift,Protocols,我知道有很多这样的问题。但是,下面是我的代码片段: protocol AProt { var a:Int { get set } } protocol BProt { var b:Int { get set } } protocol CProt { var c:Int { get set } } class A:AProt, CProt { var a = 1; var c = 3 } class B:BProt, CProt { var b = 2; var c = 30 } var a

我知道有很多这样的问题。但是,下面是我的代码片段:

protocol AProt { var a:Int { get set } }
protocol BProt { var b:Int { get set } }
protocol CProt { var c:Int { get set } }
class A:AProt, CProt { var a = 1;  var c = 3 }
class B:BProt, CProt { var b = 2; var c = 30 }

var a = A()
var b = B()
var c = a as CProt // works
c.c = 123
a = c as! A
print (a.c)
(a as CProt).c = 999 // throws error
print (a.c)
看着它就知道…就像。。。使表达式不可变。但是


虽然a as CProt.c=999失败并显示上述错误消息,但使用var c=a as CProt的变通方法仍然有效。我认为这是一个简单的编译器错误,但我想知道这里是否可以做一些事情,比如添加一个秘密关键字。

这不是一个编译器错误。CProt可以是值类型。考虑这个代码:

protocol CProt { var c:Int { get set } }
struct A: CProt { var a = 1;  var c = 3 } // Note this is a struct
var a = A()  // It's mutable
let c = a as CProt  // But this one isn't
c.c = 999  // So no surprise this fails
你认为这样行吗?不应该,因为c是一个不可变的结构。这与您在a中编写的内容相同,即CProt.c=999

问题是您希望CProt是引用类型。如果你需要,那么说:

protocol CProt:class { var c:Int { get set } } // Note the addition of :class
class A: CProt { var a = 1;  var c = 3 }
let a = A()
(a as CProt).c = 999 // Success

这不是编译器错误。CProt可以是值类型。考虑这个代码:

protocol CProt { var c:Int { get set } }
struct A: CProt { var a = 1;  var c = 3 } // Note this is a struct
var a = A()  // It's mutable
let c = a as CProt  // But this one isn't
c.c = 999  // So no surprise this fails
你认为这样行吗?不应该,因为c是一个不可变的结构。这与您在a中编写的内容相同,即CProt.c=999

问题是您希望CProt是引用类型。如果你需要,那么说:

protocol CProt:class { var c:Int { get set } } // Note the addition of :class
class A: CProt { var a = 1;  var c = 3 }
let a = A()
(a as CProt).c = 999 // Success

如果你可以简单地分配a.c=999,那么为什么要选a.c=999?@MartinR好吧,这是一个缩小的例子,整个上下文都会把问题搞砸。也许我必须重新思考,再次从后门进入整个事件。如果你可以简单地分配a.c=999,那么为什么要选a.c=999?@MartinR好吧,这是一个缩小的例子,整个背景会让问题变得更糟。也许我必须重新思考,再次从后门进入整个过程。嗨@Rob,这是我的第一个想法,但想想下面的情况:如果a是一个结构,那么var c=a作为CProt创建一个副本。因此,在as CProt的情况下,这也可以创建一个副本,因此将anthing分配给该副本没有问题。我知道这不是他们在swift中实施的方式,他们为什么不这么做?或者我在这里遗漏了什么?如果as CProt创建了一个可变副本,它将是无用的,因为它将立即被销毁。这将是非常混乱和容易出现错误的。创建一个不可变的副本是可以的,但如果您更改了它,并且您所做的更改立即丢失,这与不更改它是一样的。我说的是,它确实更改了,我的意思是,它等同于创建一个不可变的副本。它可能会也可能不会复制任何数据。但你必须把它看作是有效地创造新的价值。啊!课堂是秘密的调味品。谢谢你!对不起,我把莱德埋在那里了。编辑以使其更清晰。嗨@Rob,这是我的第一个thaught,但请考虑以下内容:如果a是一个结构,那么var c=a作为CProt创建一个副本。因此,在as CProt的情况下,这也可以创建一个副本,因此将anthing分配给该副本没有问题。我知道这不是他们在swift中实施的方式,他们为什么不这么做?或者我在这里遗漏了什么?如果as CProt创建了一个可变副本,它将是无用的,因为它将立即被销毁。这将是非常混乱和容易出现错误的。创建一个不可变的副本是可以的,但如果您更改了它,并且您所做的更改立即丢失,这与不更改它是一样的。我说的是,它确实更改了,我的意思是,它等同于创建一个不可变的副本。它可能会也可能不会复制任何数据。但你必须把它看作是有效地创造新的价值。啊!课堂是秘密的调味品。谢谢你!对不起,我把莱德埋在那里了。编辑以使其更清晰。