swiftclassstaticsubclass

Is it possible to loop over Swift subclasses and access their static var's?


I have a number of subclasses with a static var.

class A { }
class A1: A { static var intArray: [Int] = [] }
// …
class An: A { static var intArray: [Int] = [] }  

I want to loop over the subclasses using something like

func test() {
    let aTypes: [A.Type] = [A1.self, /* … */ An.self]
    for aType in aTypes {
        let nextSubclass = type(of: aType)
        nextSubclass.intArray = [0] // Error: Type 'A.Type' has no member 'intArray'
    }
}

I first thought about declaring static var intArray also in class A and to override it, but this is not allowed. I also tried to use a class var instead of a static var, but this is not allowed either.

Is there any way to achieve what I want?


Solution

  • While it is not possible to override static vars, it is possible to override class vars.

    But first, consider making A a protocol.

    protocol A {
        static var intArray: [Int] { get set }
    }
    
    class A1: A {
        static var intArray: [Int] = []
    }
    // …
    class An: A {
        static var intArray: [Int] = []
    }
    

    If A must be a class, you can use class vars like this (this is quite a lot of boilerplate):

    class A {
        class var intArray: [Int] {
            get { fatalError() }
            set { }
        }
    }
    
    class A1: A {
        private static var _intArray: [Int] = []
        override class var intArray: [Int] {
            get { _intArray }
            set { _intArray = newValue }
        }
    }
    // …
    class An: A {
        private static var _intArray: [Int] = []
        override class var intArray: [Int] {
            get { _intArray }
            set { _intArray = newValue }
        }
    }
    

    Note that you should not use type(of:) in test. aType is already the type you want:

    func test() {
        let aTypes: [A.Type] = [A1.self, /* … */ An.self]
        for aType in aTypes {
            aType.intArray = [0]
        }
    }