Override static var in a child Class Swift
Asked Answered
B

4

9

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" );
Breakwater answered 30/11, 2015 at 10:50 Comment(2)
Why do you need statics here? You can have a member variable such as furnitureType, and can override that in the initialiser of repective subclasses.Gesellschaft
Any class is instanciated, I only use class method...Breakwater
F
20

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.

Floristic answered 26/10, 2017 at 9:48 Comment(1)
just use class var instead of static var, to allow override in sub class.Centaury
I
2

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.

Incommodious answered 30/11, 2015 at 11:40 Comment(1)
I think this (+1) is the right way to tackle this problem in Swift. Use a protocol to declare the variable. I'd probably also use a protocol extension to implement the request method.Herzel
H
2

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.

Herzel answered 21/11, 2016 at 19:19 Comment(0)
E
0

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)
    }
}
Explosive answered 30/9, 2022 at 7:10 Comment(0)

© 2022 - 2025 — McMap. All rights reserved.