Including code and storage

One problem I have always had with Objective C. and now Swift, is the lack of multiple inheritance. I have certain functionality I would like to add to a number os disparate classes without having to replicate the code. Catagories (and Swift extensions) don't allow storage, and are specific to a particular class. In Objective C, I had considered the use of a simple include file, but I'm not sure it that works in Swift, and am not sure of the implications in debugging. Many classes, eg, views and view controllers, already inherit from other classes, so a common base class is out of the question. Is there any good way to do this?

Do default implementations in protocols not work for you? You can require the presence of a property in the protocol, etc.

I believe that means the (stored) properties have to be defined in the class that adopted the protocol. I have to say that I am confused by protocol extensions. The extension is to the protocol. Is that effectively the same as the class having that extension, and that the etension methods can be called from an object of that class? Then the protocol itself says what must be defined in the class for calls from the extension methods. Do I have that right?


One issue is that if i had multiple inheritance, I could define methods which need to be overriden in the new class. But that is not possible with protocols and extensions.

I don't know about Swift but for objective-c, you can use the Protocols to enforce an interface like you are wanting to do. If you specify "required" in the protocol, then when a class is designated as implementing the protocol, the compiler will tell you if it didn't implement a required method which basically allows you to "define methods which need to be overriden in the new class". The main gotcha is as you mentioned, you need to implement the properties in the class. Defnining them in the protocol does not auto synthesize in the class.

Yes, in Objective C you have to write the accessors or use "systhesize" (even with ARC).


My biggest question is if the protocol extension is effectlvely the same as a class extension. For example, I want the extension to have a getContentsJSON() method that needs to be called from a viewDidLoad override.


Later:

Actually, I think I've got something that might work. At least, the compiler is no longer complaining. Haven't run it yet. It does appear that the extension is to the class when adopting the protocol with extension.

Well, this isn't working out as well as I had hoped. Looks like you can add an extension to a protocol, or you can have a class extension adopt a protocol. The latter does not solve my problem, because it is specific to a particular class, which is what I am trying to avoid. I need the former. I'm geting linker errors.

I finally got it working, but may have uncovered a Swift bug in the process. Protocol included:

var contents: [String:AnyObject]? {get set}

Extension had:

func handleContents(jContents: [String : AnyObject]) -> Void {

contents = jContents

// updateContents(jContents)

applyBackground()

applyJSONContents()

}

Swift kept telling me to use "self.contents" and that the function had to add "mutating". However, it would then reject it. I finally added to the protocol:

func updateContents(jContents: [String : AnyObject])

which I implemented in the class and had it do "contents = jContents". That worked.

I may be missing many things as you have not shown many parts of your code, and I cannot reproduce the issue: Swift kept telling me to use "self.contents".

And I completely do not understand what you mean by However, it would then reject it.


So, just focusing on that the function had to add "mutating", it definately is not a bug.

In Swift, structs also can conform to a protocol, so methods which may modify self needs to be marked as `mutating`.

If you never make any structs conform to the protocol and you don't like to put `mutating`, you can restrict the protocol as class-only.

protocol MyProtocol: class {
    var contents: [String:AnyObject]? {get set}
    func applyBackground()
    func applyJSONContents()
}
extension MyProtocol {
    func handleContents(jContents: [String : AnyObject]) -> Void {
        contents = jContents
        applyBackground()
        applyJSONContents()
    }
}

Ah ha! That was the magic I needed, i.e., specifying "class" after the protocol. Thanks. Now, with any luck, I can add that protocol with extension to several different UIViewControllers instead of replicating the code in each.

Including code and storage
 
 
Q