In swift, why can I set a computed property of a polymorphic variable via optional chaining, but not on an unwrapped optional? -
i ran think strange error in may app. @ bottom of question complete code reproduces seeing in app, here quick demonstration.
i create 2 instances of same class, 1 declared optional conforming protocol other optional of concrete class
for both can set computed property via option chaining ie:
anoptionalinstance?.somecomputedproperty = ....
for concrete version can set property unwrapping optional
if let aninstance = anoptionalinstance { aninstance.somecomputedproperty = .... }
for polymorphic version, error message says can't set property on instance.
below complete file reproduces issue seeing.
can explain happening here?
struct mystruct { var somemember: string } protocol myprotocol { var myvar: mystruct { set } } class mytype: myprotocol { var myvar: mystruct { { return mystruct(somemember: "some string") } set { println(newvalue) } } } class usingclass { var aninstanceofmytype: myprotocol? var anotherinstanceofmytype: mytype? func somemethod() { aninstanceofmytype = mytype() aninstanceofmytype?.myvar = mystruct(somemember: "blah") if let aninstanceofmytype = aninstanceofmytype { // following line produces error :cannot assign 'myvar' in 'aninstanceofmytype' aninstanceofmytype.myvar = mystruct(somemember: "blah blah") } anotherinstanceofmytype = mytype() anotherinstanceofmytype?.myvar = mystruct(somemember: "blah") if let anotherinstanceofmytype = anotherinstanceofmytype { anotherinstanceofmytype.myvar = mystruct(somemember: "blah blah") } } }
the problem happen because trying change property of constant aninstanceofmytype
type myprotocol
.
1. why aninstanceofmytype
constant?
at first line of usingclass
, aninstanceofmytype
declared var
. conditional unwrapping
constant name aninstanceofmytype
created, , trying change property of constant
2. ok aninstanceofmytype
references instance of class, should able change properties if it's constant
since aninstanceofmytype
has myprotocol
type, contain struct
or reference instance of class
. compiler apply safer approach , avoid change properties.
solution
limit protocol adoption class types (and not structures or enumerations) adding class keyword protocol’s inheritance list. class keyword must appear first in protocol’s inheritance list, before inherited protocols:
protocol myprotocol: class { var myvar: mystruct { set } }
or
if myprotocol
updated extend anyobject
protocol myprotocol : anyobject { var myvar: mystruct { set } }
then becomes clear aninstanceofmytype
must refer instance of class, in case code compile.
Comments
Post a Comment