I have read the Swift docs and searched here, but I still am not sure about how to implement a class hierarchy where each subclass sets custom value for an inherited static property; that is:
Base class defines a static property: all instances share the same value.
Subclass overrides the static property: all instances share the same value, which is different form that of the base class.
Can the property be stored?
Also, How should I access the value of the property from within an instance method (regardless of the particular class), and get the correct value everytime? will the following code work?
class BaseClass
{
// To be overridden by subclasses:
static var myStaticProperty = "Hello"
func useTheStaticProperty()
{
// Should yield the value of the overridden property
// when executed on instances of a subclass:
let propertyValue = self.dynamicType.myStaticProperty
// (do something with the value)
}
You are so close to being there, except that you can't override a static property in a subclass — that is what it means to be static. So you'd have to use a class property, and that means it will have to be a computed property — Swift lacks stored class properties.
So:
class ClassA {
class var thing : String {return "A"}
func doYourThing() {
print(type(of:self).thing)
}
}
class ClassB : ClassA {
override class var thing : String {return "B"}
}
And let's test it:
ClassA().doYourThing() // A
ClassB().doYourThing() // B
Related
To create a singleton class, I wrote something like this:
class SingletonEx{
var name = ""
private init(){}
static let sharedInstance = SingletonEx()
func instanceMethod(){
}
static func classMethod(){
}
}
Some tutorials say final is necessary while others just ignore final keyword. After I tried subclassing SingletonEx, I got the following results.
It seems I can't write an initializer for subclass, which means I can't use an override instance method in a subclass.
As far as I know, singleton definition is all about single instantiation and accessing instance methods through the only instance. So I don't think it is necessary to use final in the singleton definition. But both my teachers and some online tutorials say it is necessary.
I got confused, since you can't create a subclass instance anyway, even you override the instance methods, you can't use it or access it, what's the point to say final is necessary for a singleton class?
If I am wrong, please point out.
Super Class
First of all you need to know the properties and methods that are marked with private are just known to the Super class and Sub classes won't access them!
A class can inherit methods, properties, and other characteristics from another class. When one class inherits from another, the inheriting class is known as a subclass, and the class it inherits from is known as its superclass. Inheritance is a fundamental behavior that differentiates classes from other types in Swift.
Classes in Swift can call and access methods, properties, and subscripts belonging to their superclass and can provide their own overriding versions of those methods, properties, and subscripts to refine or modify their behavior. Swift helps to ensure your overrides are correct by checking that the override definition has a matching superclass definition.
In your case in SingletonEx class you market init with private which means that you can create object just in the body of the class! that means no one, no where, can't create an object of SingletonEx!
If you want to a method end up in Super Class and you don't want to Sub classes overide that method you need to mark that method with final which means it's not private but its available only from Super class!
Sub Class
When class Y Inheritance from SingletonEx which means that cant create an object outside of the class ! because Super class initializer is unavailable during init() method from class Y ! While you need to call the super.init() if you want to initialize an object from Y class !
if you remove private from private init() {} from SingletonEx class you be able to create object from SingletonEx class and also from Y class !
your code should looks like this :
Swift 4 :
class SingletonEx{
var name = ""
init(){}
static let sharedInstance = SingletonEx()
func instanceMethod(){
}
static func classMethod(){
}
}
class Y : SingletonEx {
private var yName = "Y name is : "
init(name:String) {
super.init()
self.name = self.yName + name
}
}
Usage :
override func viewDidLoad() {
super.viewDidLoad()
let yObject = Y.init(name: "badGirl :D ")
print(yObject)
// --> Output : Y name is : badGirl :D
}
As the question may seem duplicated, I point out first that this is not asking for how to get a class type from an instance ( answer is using type(of:) ).
protocol Owner {
static func name() -> String
}
extension Owner {
static func name() -> String {
return "\(self)"
}
}
class Foo {
var ownerName: String
init(with owner: Owner.Type) {
ownerName = owner.name()
}
}
class Bar: Owner {
var foo = Foo(with: Bar.self)
}
The code above simply works, but imagine that I want to rename the class Bar to BarBar then I need to change the initialization of foo to Foo(with: BarBar.self) manually. Is there any keyword that can be used instead of ClassName.self (e.g. Bar.self BarBar.self) to get the class type? Something like Self or Class (they don't compile actually)
My guess is that your whole question is a red herring and that type(of:self) is exactly what you want to say. In that case, the problem is merely that var foo is declared as an instance property. There are special rules for when you are allowed to say self while initializing an instance property (rightly, because self is exactly what does not yet exist during initialization). However, there are ways around that, as I have explained elsewhere; you can make this a computed instance property, or a lazy instance property, which is initialized by a function to be executed later, and then you are allowed to say type(of:self).
Example:
internal protocol PropertyProtocol {
var property: Self {
get
}
}
The only option I see to implement it, let us say in a class is
internal final class PropertyClass: PropertyProtocol {
let property: PropertyClass
internal init(otherOne pOtherOne: PropertyClass) {
self.property = pOtherOne
}
}
But then I do not see a possibility to use it.
let test: PropertyProtocol = PropertyProtocol(...) // hmm, how?
Does Self in a protocol property type declaration always have to be optional?
As a stored property, indeed it would have to be optional for you to create an instance, as each instance would require the stored property to be assigned during initialisation – leading to recursive behaviour. Therefore Self doesn't make too much sense as a stored property; it's really more designed to be used with methods or calculated properties.
Depending on what you're using this for (seems like a fairly hypothetical example), you could implement a calculated property like so:
protocol PropertyProtocol {
var property : Self { get }
}
final class PropertyClass : PropertyProtocol {
var property : PropertyClass {
get {
return // ...
}
set {
// ...
}
}
}
That way the class itself can manage the creation of the property when it's accessed, preventing the recursive behaviour of requiring it to be assigned during initialisation.
I would like to do something similar to the following with an NSObject subclass
class Thing: NSObject {
class func defaultText() -> String { ... }
let text: String
init(text: String?) {
self.text = text ?? self.dynamicType.defaultText() // Of course, this line won't compile
super.init()
}
}
so that Thing subclasses may override defaultText() without requiring them to override the initializer. This is easy to do with a mutable stored property, but it would be nice to have it constant. Is there a way to do this?
This is a separate issue than overriding static vars in subclasses swift 1.2 . There is no desire to override a constant or a static method. The only thing in question is, in the initializer where the constant is set, is there a way to compute a value based on the specific class that is being initialized?
I have following code snippets:
protocol UpdateUIFromNativeListenerItf {
func triggerUI()
}
class WmBuildGroupsTask{
var mUfn:UpdateUIFromNativeListenerItf?
init(){/* ... */}
// ...
class func triggerRegister( ufn: UpdateUIFromNativeListenerItf ) {
mUfn = ufn // WmBuildGroupsTask.Type does not have `mUfn`
}
}
Form other class I call:
var ufn:UpdateUIFromNativeListenerItf = self
WmBuildGroupsTask.triggerRegister(ufn)
How can I pass delegate to static method?
Do I need create singleton for class WmBuildGroupsTask?
I tried also to write class var mUfn:UpdateUIFromNativeListenerItf?
But get: Class var not yet supported
Thanks,
Static stored properties are not supported in swift classes (yet), but they are in structs. So you can create an inline private struct and define your static properties there:
class WmBuildGroupsTask{
private struct Static {
static var mUfn:UpdateUIFromNativeListenerItf?
}
init(){/* ... */}
// ...
class func triggerRegister( ufn: UpdateUIFromNativeListenerItf ) {
Static.mUfn = ufn // WmBuildGroupsTask.Type does not have `mUfn`
}
}
The downside is that you have to access the static property prefixing it with the struct name - but I guess that's an acceptable tradeoff.
There is also another obvious way to solve the problem: turn the class into a struct, so obvious that it's enough to just mention it. Just a consideration: structs and classes are not interchangeable, they have their own pros and cons.
You are trying to access a member variable in a static context. mUfn is stored for an instance of your class, not for the class itself.