Swift call class function from corresponding subclass in superclass function

11,002

Solution 1

I think I caught what you mean. You create a Base class, implementing an initializer and a class (static) function:

class Base {
    class func dummyDict() -> Dictionary<String, String> {
        return ["base1": "val1"]
    }

    init() {
        for (key, value) in self.dynamicType.dummyDict() {
            println("encoding \(value) for key \(key)")
        }
    }
}

Next you want to create subclasses, and have the initializer to call an overridden version of the dummyDict method. You simply have to override that method:

class Subclass1 : Base {
    override class func dummyDict() -> Dictionary<String, String> {
        return ["subclass1": "sub1"]
    }
}

Now, when you create an instance of Subclass1, what's printed is:

encoding sub1 for key subclass1

which is the expected output.

Note the for loop in the initializer is using self.dynamicType.dummyDict() rather than Base.dummyDict(). The latter always calls the class method defined in the Base class, whereas the former calls it in the scope of the actual class inherited from Base

Solution 2

dynamicType is deprecated in Swift 3. We must use type(of:).

So Antonio's example is now:

class Base {
    class func dummyDict() -> [String: String] {
        return ["base1": "val1"]
    }

    init() {
        for (key, value) in type(of: self).dummyDict() {
            print("encoding \(value) for key \(key)")
        }
    }
}

class Subclass1 : Base {
    override class func dummyDict() -> [String: String] {
        return ["subclass1": "sub1"]
    }
}
Share:
11,002
the_critic
Author by

the_critic

Updated on July 02, 2022

Comments

  • the_critic
    the_critic almost 2 years

    I would like to implement init(coder aDecoder: NSCoder!) in a superclass, and use it in all subclasses by calling a class method on the particular subclass in the superclass at runtime.

    MySuperClass

    class func dummyDict() -> NSDictionary
    
    init(coder aDecoder: NSCoder!) {
    
        for(key,value) in self.class.dummyDict(){
                          --------------------
                                   ^
                                   |
                                   |
                     Get this from the corresponding subclass at runtime!
    
            NSLog("encoding \(value) for key \(key)")
        }
    
    }
    

    Is it possible that subclasses from MySuperClass access the class function dummyDict() at runtime ?

  • user102008
    user102008 almost 10 years
    "The class() method would return AnyClass! and the Compiler wouldn't know the type at compiler time... " So? The object_getClass() function also returns AnyClass! and that's not a problem.
  • user102008
    user102008 almost 10 years
    It doesn't. But that doesn't mean the function shouldn't exist.
  • user102008
    user102008 almost 10 years
    I said object_getClass, not objc_getClass; and the type of the Test class is Test.Type. If you do let cls: Test.Type = object_getClass(self) as Test.Type; println("\(cls.dummy())") in place of your println above, it indeed works.
  • user102008
    user102008 almost 10 years
    Anyway, when you wrote "self.class is not available in swift AFAICS -- as that would be a major problem for statically typing stuff" which sounds like you're saying the class method isn't available in Swift because its type would somehow be a problem. But I showed that object_getClass does the same thing and also returns AnyClass!, and it is available in Swift and not a problem. That shows that its type is not a problem and they could have made the class method available in Swift; they just didn't, for other reasons.
  • AliSoftware
    AliSoftware almost 10 years
    I was trying to do the same thing but can't make it to work, since the compiler generates an error telling me that I can't use self.dynamicType.dummyDict() as we can't use self inside of an init method ("Use of self in delegating initializer before self.init is called"). Any idea?
  • Eike
    Eike almost 9 years
    Hey @AliSoftware, at least in swift 2.0 u can use the dynamicType self.dynamicType.dummyDict() in the init function. Even before init() is called. Otherwise try to call it after init() if that is possible for you.