Stored Property on Protocol Extension


(Tanner) #1

Hey Swift Users,

I was wondering how you all work around not being able to add stored properties in extensions (especially protocol extensions).

I ran into an issue recently where I needed an internal stored variable for a protocol, but I didn't want the conformer to worry about implementing the variable.

I ended up using something like this to achieve the effect.

    extension MyProtocol {
        private var address: String {
            mutating get {
                var id = ""
                withUnsafePointer(to: &self) { id = "\($0)"}
                return id
            }
        }

        var myStoredVar: Bool {
            mutating get {
                return _storage[address] ?? false
            }
            set {
                _storage[address] = newValue
            }
        }
    }

Obviously not ideal, but I don't see another way to achieve this besides subclassing (which has its own problems for my situation).

Wondering if anyone has run into this and come up with a better solution or other type of work around.

Thanks!
Tanner


(Daniel Dunbar) #2

Hey Swift Users,

I was wondering how you all work around not being able to add stored properties in extensions (especially protocol extensions).

I ran into an issue recently where I needed an internal stored variable for a protocol, but I didn't want the conformer to worry about implementing the variable.

I ended up using something like this to achieve the effect.

   extension MyProtocol {
       private var address: String {
           mutating get {
               var id = ""
               withUnsafePointer(to: &self) { id = "\($0)"}
               return id

BTW, you can write `return withUnsafePointer(to: &self) { "\($0)" }` instead.

           }
       }

       var myStoredVar: Bool {
           mutating get {
               return _storage[address] ?? false
           }
           set {
               _storage[address] = newValue
           }
       }
   }

Obviously not ideal, but I don't see another way to achieve this besides subclassing (which has its own problems for my situation).

Wondering if anyone has run into this and come up with a better solution or other type of work around.

I don't have a better answer to this part.

This particular solution only works if it is ok for `_storage[address]` to potentially be reused by a new instance, though (if the old instance is deallocated and the new one is allocated in its place).

- Daniel

···

On Sep 11, 2016, at 6:12 PM, Tanner Nelson via swift-users <swift-users@swift.org> wrote:

Thanks!
Tanner
_______________________________________________
swift-users mailing list
swift-users@swift.org
https://lists.swift.org/mailman/listinfo/swift-users


(Zhao Xin) #3

​I don't know why the limit exists. Technical or on purpose. I hope someone
inside can answer this.

Zhaoxin​

···

On Mon, Sep 12, 2016 at 11:55 PM, Daniel Dunbar via swift-users < swift-users@swift.org> wrote:

> On Sep 11, 2016, at 6:12 PM, Tanner Nelson via swift-users < > swift-users@swift.org> wrote:
>
> Hey Swift Users,
>
> I was wondering how you all work around not being able to add stored
properties in extensions (especially protocol extensions).
>
> I ran into an issue recently where I needed an internal stored variable
for a protocol, but I didn't want the conformer to worry about implementing
the variable.
>
> I ended up using something like this to achieve the effect.
>
> extension MyProtocol {
> private var address: String {
> mutating get {
> var id = ""
> withUnsafePointer(to: &self) { id = "\($0)"}
> return id

BTW, you can write `return withUnsafePointer(to: &self) { "\($0)" }`
instead.

> }
> }
>
> var myStoredVar: Bool {
> mutating get {
> return _storage[address] ?? false
> }
> set {
> _storage[address] = newValue
> }
> }
> }
>
> Obviously not ideal, but I don't see another way to achieve this besides
subclassing (which has its own problems for my situation).
>
> Wondering if anyone has run into this and come up with a better solution
or other type of work around.

I don't have a better answer to this part.

This particular solution only works if it is ok for `_storage[address]` to
potentially be reused by a new instance, though (if the old instance is
deallocated and the new one is allocated in its place).

- Daniel

>
> Thanks!
> Tanner
> _______________________________________________
> swift-users mailing list
> swift-users@swift.org
> https://lists.swift.org/mailman/listinfo/swift-users

_______________________________________________
swift-users mailing list
swift-users@swift.org
https://lists.swift.org/mailman/listinfo/swift-users


(Dan Stenmark) #4

There's no good way of using extensions to expand the storage of an external module's type unless you're using Associated Objects underneath, but that has heavy performance implications (especially in threaded cases, which would require global locks on the associated object store). At most, I'd support a proposal for stored properties in extensions that reside in the same module as the class declaration, but it sounds like the team has bigger fish to fry right now.

If possible, consider subclassing to extend a type's storage instead.

Dan

···

Sent from my iPhone

On Sep 12, 2016, at 3:50 PM, Zhao Xin via swift-users <swift-users@swift.org> wrote:

​I don't know why the limit exists. Technical or on purpose. I hope someone inside can answer this.

Zhaoxin​

On Mon, Sep 12, 2016 at 11:55 PM, Daniel Dunbar via swift-users <swift-users@swift.org> wrote:

> On Sep 11, 2016, at 6:12 PM, Tanner Nelson via swift-users <swift-users@swift.org> wrote:
>
> Hey Swift Users,
>
> I was wondering how you all work around not being able to add stored properties in extensions (especially protocol extensions).
>
> I ran into an issue recently where I needed an internal stored variable for a protocol, but I didn't want the conformer to worry about implementing the variable.
>
> I ended up using something like this to achieve the effect.
>
> extension MyProtocol {
> private var address: String {
> mutating get {
> var id = ""
> withUnsafePointer(to: &self) { id = "\($0)"}
> return id

BTW, you can write `return withUnsafePointer(to: &self) { "\($0)" }` instead.

> }
> }
>
> var myStoredVar: Bool {
> mutating get {
> return _storage[address] ?? false
> }
> set {
> _storage[address] = newValue
> }
> }
> }
>
> Obviously not ideal, but I don't see another way to achieve this besides subclassing (which has its own problems for my situation).
>
> Wondering if anyone has run into this and come up with a better solution or other type of work around.

I don't have a better answer to this part.

This particular solution only works if it is ok for `_storage[address]` to potentially be reused by a new instance, though (if the old instance is deallocated and the new one is allocated in its place).

- Daniel

>
> Thanks!
> Tanner
> _______________________________________________
> swift-users mailing list
> swift-users@swift.org
> https://lists.swift.org/mailman/listinfo/swift-users

_______________________________________________
swift-users mailing list
swift-users@swift.org
https://lists.swift.org/mailman/listinfo/swift-users

_______________________________________________
swift-users mailing list
swift-users@swift.org
https://lists.swift.org/mailman/listinfo/swift-users