2

So here is a thing I wanted to use the protocol oriented programming paradigm with the OOP to have some of variables assigned to main classes like let's say UIView, UIImageView etc. but then have some other variables defined in their subclasses. To achieve that one need to make those variables "optional" and is Swift a way to do that is to extend a protocol. Everything works great until I decide to add those subclasses instances to an array and read those variables later... That is the very same object (same pointer) but when reading that variable after adding to an array it uses a getter from the protocol extension not the one from the subclass.

protocol SomeProtocol {
    var foo: String { get }
    var foo2: String { get }
}

extension SomeProtocol {
    var foo2: String {
        return "value from extension"
    }
}

extension UIView: SomeProtocol {
    var foo: String {
        return "value from UIView"
    }
}

class SomeView: UIView {
    var foo2: String {
        return "value from someView"
    }
}

let someView = SomeView()
print(someView.foo2)

"value from someView"

var array = [SomeProtocol]()
array.append(someView)

print(array.first?.foo2)

"value from extension"

I know that it's an array of objects conforming to the SomeProtocol and that's probably a reason. The thing is I want to have an array of objects of different classes conforming to that protocol and be able to access a getter from those objects not from the protocol extension. It would be probably possible if I use an @objc protocol and an optional variable but I would prefer to have pure Swift solution.

matthewfx
  • 1,244
  • 1
  • 9
  • 14
  • 1
    Compare https://stackoverflow.com/q/44703205/2976878. Although you cannot override a member defined in an extension (well, not unless you expose to Obj-C). – Hamish Oct 19 '17 at 10:43

1 Answers1

-1

Your array has defined type of SomeProtocol so calling to object array directly you will reach code in extension.

To get desired effect you have to map object to expected type:

if let someView = array.first as? SomeView {
    print(someView.foo2)
}

will give you expected:

value from someView

Tomasz Czyżak
  • 1,118
  • 12
  • 13
  • Yes I know that but as explained in my question I would like the array to consist of instances of other classes confirming to that protocol. I don't want to check for all possible successful castings to get an expected getter. Looks like the only solution is what I mention: to use an @objc protocol and optional variables to achieve it... – matthewfx Oct 19 '17 at 18:49