【问题标题】:How to return subclass objects from its base class static method?如何从其基类静态方法返回子类对象?
【发布时间】:2023-03-20 10:47:01
【问题描述】:

在 Swift 中,我想让我的基类静态方法在从子类调用静态方法时返回其子类对象。

当返回一个子类对象时,我可以通过使用 init() 来实现。 但是当返回多个子类对象时,就不能使用init()了。

而我不仅要从父静态方法返回子类对象,还要在父静态方法中实现一些除实例化以外的逻辑,让每个子类的静态方法继承父静态方法的行为。

我有 3 个子类。所以,我不想在3个子类的静态方法中写相同的代码。 我该怎么办?

如果可能,我也想使用静态方法而不是 init() 来返回单个子类对象。

class Base {
    
    func f() {
        print("base class")
    }
    
    // this does not works. it creates a base class object.
    static func createSubclassObject() -> Base {
        return Base()
    }
    
    // this works. it creates a subclass object.
    init() {
    }
    
    // this does not work. base class objects are created.
    static func createSubclassObjects(count: Int) -> [Base] {
        var objects = [Base]()
        for _ in 0 ..< count {
            objects.append(Base())
        }
        return objects
    }

    /* probably I need something like this. but this code generates a compile error
    static func createSubclassObjects(count: Int) -> [Self] {
        var objects = [Self]()
        for _ in 0 ..< count {
            objects.append(Self())
        }
        return objects
    }
    */

    // generic also does not work. this returns a base class object.
    static func createSubclassObjectByGeneric<T: Base>() -> T {
        return T()
    }

}
class Sub: Base {
    override func f() {
        print("sub class")
    }
}
print(Sub().f())
// sub class・
print(Sub.createSubclassObject().f())
// base class
Sub.createSubclassObjects(count: 2).forEach {
    print($0.f())
}
// base class
// base class
print(Sub.createSubclassObjectByGeneric().f())
// base class

【问题讨论】:

    标签: swift


    【解决方案1】:

    您需要返回Self,而不是Base

    static func createSubclassObject() -> Self {
      .init()
    }
    
    required init() { }
    

    另外,不要使用 for 循环。有一个为你正在做的事情预先准备好的数组初始化器。

    static func createSubclassObjects(count: Int) -> [Base] {
      .init(repeating: createSubclassObject(), count: count)
    }
    

    【讨论】:

    • 感谢您的精彩回答!这很完美。你的答案是我一直在寻找的。我发现Array(repeating: Self.init(), count: count) 也返回子类对象。但是Array(repeating: .init(), count: count) 返回基类对象。
    【解决方案2】:

    以下代码有效。但我认为应该有更好的解决方案,因为我不想在父类中定义class func sub(),并在每个子类中覆盖class func sub()

    编辑:查看 Jessy 的回答,这是更好的解决方案。

    class Base {
        
        func f() {
            print("base class")
        }
        
        static func createSubclassObjects(count: Int) -> [Base] {
            var objects = [Base]()
            for _ in 0 ..< count {
                //objects.append(Base())
                objects.append(Self.sub())
            }
            return objects
        }
        
        class func sub() -> Base {
            Base()
            // or use fatalError() if you don't need to call createSubclassObjects(count: Int) from the base class
        }
        
    }
    
    class Sub1: Base {
        
        override func f() {
            print("sub1 class")
        }
        
        override class func sub() -> Base {
            Sub1()
        }
        
    }
    
    class Sub2: Base {
        
        override func f() {
            print("sub2 class")
        }
        
        override class func sub() -> Base {
            Sub2()
        }
        
    }
    
    Base.createSubclassObjects(count: 2).forEach {
        print($0.f())
    }
    // base class
    // base class
    
    
    Sub1.createSubclassObjects(count: 2).forEach {
        print($0.f())
    }
    // sub1 class
    // sub1 class
    
    
    Sub2.createSubclassObjects(count: 2).forEach {
        print($0.f())
    }
    // sub2 class
    // sub2 class
    
    

    【讨论】:

      猜你喜欢
      • 2012-07-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-04-05
      • 2013-11-16
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多