Damien Romito
Damien Romito

Reputation: 10065

Override static var in a child Class Swift

To factorize my code, I want to set a stringKey from an Child class which I'll get in a class func in the parent class:

Chair.request();
Table.request();

class Furniture: NSObject {

    static let requestKey : String!

    class func request(){

        print("class key => \(self.requestKey)")
        ...
    }
}

class Chair: Furniture {
    static let requestKey : String = "jsonchairs"
} 

class Table: Furniture {
    static let requestKey : String = "tables"
} 

Of course, I have the precompiled error message

Property does not override any property from its superclass

Is there a solution to do this, or do I need to pass the key as parameter? like this:

Chair.request(key : "jsonchairs" );
Table.request(key : "tables" );

Upvotes: 9

Views: 13753

Answers (4)

Milan Savaliya M
Milan Savaliya M

Reputation: 304

Base class:

   class RSBaseViewController: UIViewController {

    class var viewControllerId: String {
        return "viewControllerId"
    }
    
    class var storyboardName: String {
        return "storyboardName"
    }
    
    static func fromStoryboard() -> Self {
        print("storyboardName", storyboardName)
        print("viewControllerId", viewControllerId)
        let vc = UIStoryboard(name: storyboardName, bundle: nil).instantiateViewController(withIdentifier: viewControllerId)
        return vc as! Self
    }
}

Child class:

    class ViewController: RSBaseViewController {
    
    override static var viewControllerId: String { return "HomeVC" }
    override static var storyboardName: String { return "Main"}
    
    override func viewDidLoad() {
        super.viewDidLoad()
        let val = TestVC.fromStoryboard()
        val.id = "test"
        self.navigationController?.pushViewController(val, animated: true)
        print(val)
    }
}

Upvotes: 0

Raimundas Sakalauskas
Raimundas Sakalauskas

Reputation: 2294

Just had the same problem. Use computed properties - these can be overriden.

Base class:

class BaseLanguage {
    class var language: String {
        return "Base"
    }

    static func getLocalized(key: String) -> String {
        print("language: \(language)");
    }
}

Child class:

class German: BaseLanguage {
    override class var language: String {
        return "de"
    }
}

If you can't use computed properties for some reason, you can always wrap variable properties in private singleton. The class exposes external interface as as static, but inside it has static private reference to its instance. You can change value of any property (as long as it's variable) within init method.

Upvotes: 20

Rob
Rob

Reputation: 437642

I believe vale is correct, that one would generally consider protocols in this case. In addition to providing the protocol definition for the requestKey, I'd also implement request as a default implementation of the protocol:

// define Furniture protocol

protocol Furniture {
    static var requestKey: String { get }
    static func request()
}

// implement default implementation in extension

extension Furniture {
    static func request() {
        print("class key => \(self.requestKey)")
    }
}

// both Chair and Table conform to this protocol

class Chair: Furniture {
    static let requestKey = "jsonchairs"
}

class Table: Furniture {
    static let requestKey = "tables"
} 

Note, I'm assuming that the Furniture base class was not really needed, so I co-opted that for my protocol. You just need to decide whether you really need this Furniture base class or not. My rule of thumb as I've transitioned from object-oriented to protocol-oriented programming is whether there can be concrete instances of this Furniture type, or whether it's more of an abstract/virtual type that is used merely to define some shared behavior of other types that will ultimately be instantiated (i.e. Chair and Table types).

If Furniture truly is a concrete type, then you'll have to find a way to achieve what you want without using static types or methods because you cannot override statics. If you show us how you're using this Furniture type in addition to the Chair and Table types, we might be able to help you refactor this in such a manner that you won't need the static methods/types.

But if Furniture is not a concrete type, then I'd suggest pushing yourself and see whether you can accomplish everything you need with a protocol. When you make the shift from object-oriented programming to protocol-oriented programming, it takes a little time to grok it. Just don't be too Crusty. For more information, see WWDC 2015 video Protocol-Oriented Programming in Swift or the equivalent WWDC 2016 video Protocol and Value Oriented Programming in UIKit Apps.

As an aside, even if you adopt this protocol-oriented pattern, I wouldn't be inclined to use static types/methods in your particular example, but that's a separate question. The above protocol-oriented pattern works equally well for static methods as it does for instance methods.

Upvotes: 2

vale
vale

Reputation: 1426

You can use protocols for that. Just make them both conform to RequestKeyProtocol fir example and than implement it in each case.

protocol RequestKeyProtocol {
 var requestKey: String
}




 class myClass: RequestKeyProtocol {
   var requestKey = "myKey"
   }

If you need a default value look into protocols extensions. Take a look at this year WWDC video about protocols as well.

Upvotes: 2

Related Questions