Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Swift: implement a protocol variable as a lazy var?

It seems that it's not possible to implement a variable that's required by a protocol, with a lazy variable. For example:

protocol Foo {   var foo: String { get } }  struct Bar: Foo {   lazy var foo: String = "Hello World" } 

Compiler complains that Type 'Bar' does not conform to protocol 'Foo'.

It's also not possible to add the lazy keyword in the protocol declaration, since then you get 'lazy' isn't allowed on a protocol requirement error.

So is this not at all possible?

like image 898
Kevin Renskers Avatar asked Jan 02 '18 14:01

Kevin Renskers


People also ask

How do you make a lazy variable in Swift?

You indicate a lazy stored property by writing the lazy modifier before its declaration. You must always declare a lazy property as a variable (with the var keyword), because its initial value might not be retrieved until after instance initialization completes.

How does Swift define lazy VAR?

A lazy var is a property whose initial value is not calculated until the first time it's called. It's part of a family of properties in which we have constant properties, computed properties, and mutable properties.

CAN protocol have a variable in Swift?

You can use a protocol in many places where other types are allowed, including: As a parameter type or return type in a function, method, or initializer. As the type of a constant, variable, or property.

Is lazy var thread safe Swift?

Another problem is that lazy var is not thread-safe which means the closure can get executed multiple times due to accesses from different threads.


1 Answers

Citing the Language Guide - Properties - Lazy Stored Properties [emphasis mine]:

A lazy stored property is a property whose initial value is not calculated until the first time it is used.

I.e., the value is mutated upon first usage. Since foo has been blueprinted in the Foo protocol as get, implicitly nonmutating get, the value type Bar does not fulfil this promise with its lazy property foo, a property with a mutating getter.

Changing Bar to a reference type will allow it to fulfil the Foo blueprint (as mutating a property of a reference type doesn't mutate the type instance itself):

protocol Foo {     var foo: String { get } }  class Bar: Foo {     lazy var foo: String = "Hello World" } 

Alternative, specify in the blueprint of the foo property of Foo that it has a mutating getter.

protocol Foo {     var foo: String { mutating get } }  struct Bar: Foo {     lazy var foo: String = "Hello World" } 

See the following Q&A for some additional details of the mutating/nonmutating specifiers for getters and setters:

  • Swift mutable set in property
like image 187
dfrib Avatar answered Oct 04 '22 10:10

dfrib