Reputation: 10065
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
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
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
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
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