devios devios - 5 months ago 14
Swift Question

Can a Swift class be extended multiple times with the same methods?

I am designing a framework that uses protocols and extensions to allow for third-parties to add support for my framework to their existing classes.

I'd also like to include some built-in extensions for known classes like UIView, but I don't want to prevent users from defining their own additional support for the same classes.

My question is is there any way that I can extend the same class twice, and override the same (protocol) method in that class both times, while still having some way to call the other if the first one fails.

Elaboration: I really have three goals here I want to achieve:


  1. I want to allow users of my framework to provide their own extensions for their own (or any) UIView subclasses.

  2. I also need some way to allow general behavior that can apply to all UIViews as a fallback option (i.e. if the specific class extension can't handle it, fall back on the generic UIView extension).

  3. I'd also like to separate out my own implementation, by providing some built-in generic view handling, but in such a way that it doesn't prevent third parties from also defining their own additional generic handling. (If I can't do this, it's not a big deal, the first two parts are the most important.)



I have part 1 working already. The problem is how to get this fallback behavior implemented. If I do it all with extensions, the subclass will override the superclass's implementation of the protocol method. It could call
super.method
, but I'd like to avoid putting that responsibility on the subclass (in case the author forgets to call
super
).

I'd like to do this all from the framework code: first, call the object's protocol method. If it returns false, I'd like to somehow call the generic UIView handler.

Now that I'm typing it all out, I'm wondering if I can just use a different method for the generic fallback and be done with it. I just figured it would be elegant if I could do it all with one method.

Answer

Overriding a single protocol method twice in 2 separate extensions wouldn't work, because the protocol method names would collide. Once compiled, they're all just methods on the same class. With that in mind, perhaps put all the protocol methods in their own extension & call them from within the other ones?

The following could be one general option. Could get messy if you decide to keep adding additional extension functionality.

    class baseClass {
           //stuff
    }

    extension baseClass: myProtocol {

        override func myProtocolMethod(args) -> returnType {
           //Repeat this in a separate extension & your method names collide     
            var status: Bool

          //protocol method code sets status as appropriate... 

          return status = true ? optOne(status) : optTwo(status)                 

        }

        func optOne(status:Bool) -> returnType{
            //do the 'true' thing
            return returnType
        }

        func optTwo(status:Bool) -> returnType{
            //do the 'false' thing
            return returnType
        }
    } 

    extension baseClass {
        var oneExtension = myProtocolMethod(someArg)
    }

    extension baseClass {
        var twoExtension = myProtocolMethod(someArg)
    }
Comments