Overriding methods in Swift extensions

前端 未结 5 1511
隐瞒了意图╮
隐瞒了意图╮ 2020-11-22 16:13

I tend to only put the necessities (stored properties, initializers) into my class definitions and move everything else into their own extension, kind of like a

5条回答
  •  Happy的楠姐
    2020-11-22 16:29

    This answer it not aimed at the OP, other than the fact that I felt inspired to respond by his statement, "I tend to only put the necessities (stored properties, initializers) into my class definitions and move everything else into their own extension ...". I'm primarily a C# programmer, and in C# one can use partial classes for this purpose. For example, Visual Studio places the UI-related stuff in a separate source file using a partial class, and leaves your main source file uncluttered so you don't have that distraction.

    If you search for "swift partial class" you'll find various links where Swift adherents say that Swift doesn't need partial classes because you can use extensions. Interestingly, if you type "swift extension" into the Google search field, its first search suggestion is "swift extension override", and at the moment this Stack Overflow question is the first hit. I take that to mean that problems with (lack of) override capabilities are the most searched-for topic related to Swift extensions, and highlights the fact that Swift extensions can't possibly replace partial classes, at least if you use derived classes in your programming.

    Anyway, to cut a long-winded introduction short, I ran into this problem in a situation where I wanted to move some boilerplate / baggage methods out of the main source files for Swift classes that my C#-to-Swift program was generating. After running into the problem of no override allowed for these methods after moving them to extensions, I ended up implementing the following simple-minded workaround. The main Swift source files still contain some tiny stub methods that call the real methods in the extension files, and these extension methods are given unique names to avoid the override problem.

    public protocol PCopierSerializable {
    
       static func getFieldTable(mCopier : MCopier) -> FieldTable
       static func createObject(initTable : [Int : Any?]) -> Any
       func doSerialization(mCopier : MCopier)
    }
    

    .

    public class SimpleClass : PCopierSerializable {
    
       public var aMember : Int32
    
       public init(
                   aMember : Int32
                  ) {
          self.aMember = aMember
       }
    
       public class func getFieldTable(mCopier : MCopier) -> FieldTable {
          return getFieldTable_SimpleClass(mCopier: mCopier)
       }
    
       public class func createObject(initTable : [Int : Any?]) -> Any {
          return createObject_SimpleClass(initTable: initTable)
       }
    
       public func doSerialization(mCopier : MCopier) {
          doSerialization_SimpleClass(mCopier: mCopier)
       }
    }
    

    .

    extension SimpleClass {
    
       class func getFieldTable_SimpleClass(mCopier : MCopier) -> FieldTable {
          var fieldTable : FieldTable = [ : ]
          fieldTable[376442881] = { () in try mCopier.getInt32A() }  // aMember
          return fieldTable
       }
    
       class func createObject_SimpleClass(initTable : [Int : Any?]) -> Any {
          return SimpleClass(
                    aMember: initTable[376442881] as! Int32
                   )
       }
    
       func doSerialization_SimpleClass(mCopier : MCopier) {
          mCopier.writeBinaryObjectHeader(367620, 1)
          mCopier.serializeProperty(376442881, .eInt32, { () in mCopier.putInt32(aMember) } )
       }
    }
    

    .

    public class DerivedClass : SimpleClass {
    
       public var aNewMember : Int32
    
       public init(
                   aNewMember : Int32,
                   aMember : Int32
                  ) {
          self.aNewMember = aNewMember
          super.init(
                     aMember: aMember
                    )
       }
    
       public class override func getFieldTable(mCopier : MCopier) -> FieldTable {
          return getFieldTable_DerivedClass(mCopier: mCopier)
       }
    
       public class override func createObject(initTable : [Int : Any?]) -> Any {
          return createObject_DerivedClass(initTable: initTable)
       }
    
       public override func doSerialization(mCopier : MCopier) {
          doSerialization_DerivedClass(mCopier: mCopier)
       }
    }
    

    .

    extension DerivedClass {
    
       class func getFieldTable_DerivedClass(mCopier : MCopier) -> FieldTable {
          var fieldTable : FieldTable = [ : ]
          fieldTable[376443905] = { () in try mCopier.getInt32A() }  // aNewMember
          fieldTable[376442881] = { () in try mCopier.getInt32A() }  // aMember
          return fieldTable
       }
    
       class func createObject_DerivedClass(initTable : [Int : Any?]) -> Any {
          return DerivedClass(
                    aNewMember: initTable[376443905] as! Int32,
                    aMember: initTable[376442881] as! Int32
                   )
       }
    
       func doSerialization_DerivedClass(mCopier : MCopier) {
          mCopier.writeBinaryObjectHeader(367621, 2)
          mCopier.serializeProperty(376443905, .eInt32, { () in mCopier.putInt32(aNewMember) } )
          mCopier.serializeProperty(376442881, .eInt32, { () in mCopier.putInt32(aMember) } )
       }
    }
    

    Like I said in my introduction, this doesn't really answer the OP's question, but I'm hoping this simple-minded workaround might be helpful to others who wish to move methods from the main source files to extension files and run into the no-override problem.

提交回复
热议问题