Using an overriden static property during initialization

半城伤御伤魂 提交于 2019-12-13 03:34:29

问题


I would like to create a class with a static property that subclasses can override, which would be used to initialize instances. So far, I've tried to accomplish this like this:

import Cocoa

class A: NSObject {
    class var staticProperty: String {
        return "A"
    }

    var property: String = A.staticProperty
}

class B: A {
    override class var staticProperty: String {
        return "B"
    }
}

This does not work, since B().property still returns "A". How could I change this code so that property contains the value specified by the subclass? Any help would be appreciated!

Edit I would like to initialize property with the value of staticProperty, so this could also look like this:

var property: SomeClass = SomeClass(A.staticProperty)

But then, this initialization should still use "A" for class A, and "B" for class B.

Edit 2 (After @RakeshaShastri's comment) For my specific use-case, I need property to be stored (so not computed) and non-lazy.

Edit 3 In short, I'm trying to build a Realm model class which has a few to-many relationships to other models. For these models (which are quite similar), I'm trying to create a superclass which contains the shared functionality, amongst which is also the inverse relationship. Therefore, I want to have a static property which contains the key in the first model to either of the other models, and then initialize a LinkingObjects property using this key name. Since Realm does not allow this to be lazy or computed, I cannot use these functionalities here.


回答1:


If you inherit from NSObject why not using it ?

import Cocoa

class A: NSObject {
    var property: String
    public override init() {
        let str = type(of: self).perform(#selector(getter: type(of: self).staticProperty))?.takeUnretainedValue() as! String
        property = str

    }

    @objc class var staticProperty: String {
        return "A"
    }

}

class B: A {
    override class var staticProperty: String {
        return "B"
    }
}




回答2:


You can do this with this aproach

class A {
   var prop: String{
       return "A"
   }

 }

class B: A {
  override var prop: String{
      return "B"
   }
}

print(A().prop) // "PRINTS A"
print(B().prop) // "PRINTS B"



回答3:


A.staticProperty will use static dispatch and will always point to A's class property. You need dynamic dispatch here, aka type(of: self).

However, self needs an instance to work with, thus var property: String = type(of: self.staticProperty won't compile.

However, lazy properties can work around this limitation, so you could declare property as a lazy one:

class A: NSObject {
    class var staticProperty: String {
        return "A"
    }

    private(set) lazy var property: String = { type(of: self).staticProperty }()
}

class B: A {
    override class var staticProperty: String {
        return "B"
    }
}

print(B().property) // B

P.S. the private(set) part is just something I usually do, I rarely allow extrinsic factors to change my object.

Update As @MartinR has pointed out, lazy is not a choice for the OP. An alternative solution that doesn't use a lazy var is to use a "shadowing" property:

class A: NSObject {
    class var staticProperty: String {
        return "A"
    }

    private var _property: String?
    var property: String {
        get {
            return _property ?? type(of: self).staticProperty
        }
        set {
            _property = newValue
        }
    }
}

class B: A {
    override class var staticProperty: String {
        return "B"
    }
}

let b = B()
print(b.property)  // B
b.property = "B'"
print(b.property) // B'


来源:https://stackoverflow.com/questions/52670640/using-an-overriden-static-property-during-initialization

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!