2 Replies
      Latest reply on Jan 8, 2019 8:02 AM by eblu
      eblu Level 1 Level 1 (0 points)

        I've seen this before, but it was so advanced for me that it didn't stick. I may be trying to do something that might not work, but I thought I'd ask.

         

        my class has an Init function that let's me 'copy' properties form another object. it goes like this:

        init(dup: someClass)

         

        that class has a property that is an array of anotherClass:

        var array : [otherClass] = []

         

        the otherClass also uses the init(dup:) method, But... otherClass has subClasses. So the array may be populated by any of these classes.

         

        my goal is to duplicate the array like this:

        self.array = dup.array.map({ otherClass(dup:$0 })

         

        but the subClasses make this difficult, because I cannot know in advance what class to instantiate.

        now to the question: I think there is a way to phrase it so that you do not have to know the class type... but I have no idea how to phrase it.

        something like:

        self.array = dup.array.map({ $0.class(dup:$0 })

        ????

        • Re: class init question
          eskimo Apple Staff Apple Staff (11,495 points)

          If you’re committed to object-oriented programming in Swift, it’s reasonable to take your cues from other object-oriented environments.  In this case you can solve your problem by doing exactly what you’d do in Objective-C, that is, implement a copy method in your base class and require all of the subclasses to override that.  For example:

          class SomeClass {
          
              init() {
                  self.array = []
              }
          
              init(dup: SomeClass) {
                  self.array = dup.array.map { $0.copy() }
              }
          
              var array: [OtherClassBase]
          }
          
          class OtherClassBase {
              func copy() -> OtherClassBase {
                  fatalError()
              }
          }
          
          class OtherClassSub1 : OtherClassBase {
              override func copy() -> OtherClassBase {
                  return OtherClassSub1()
              }
          }
          
          class OtherClassSub2 : OtherClassBase {
              override func copy() -> OtherClassBase {
                  return OtherClassSub2()
              }
          }
          
          let s = SomeClass()
          s.array.append(OtherClassSub1())
          s.array.append(OtherClassSub2())
          let sDup = SomeClass(dup: s)

          Share and Enjoy

          Quinn “The Eskimo!”
          Apple Developer Relations, Developer Technical Support, Core OS/Hardware
          let myEmail = "eskimo" + "1" + "@apple.com"

            • Re: class init question
              eblu Level 1 Level 1 (0 points)

              Hi Eskimo!

              yeah... requiremnets make that unworkable. Or at least that's what I thought when I decided i needed an init method, instead of a copy method. I just went through the dataflow, and I didn't run into any roadblocks... maybe this is one of those times that getting a slightly new perspective makes a difference. Anyway... all of this falls where it is because of another Object Oriented Language anyway. NSPasteboardWriting, is the problem. the way

              public func pasteboardPropertyList(forType type: NSPasteboard.PasteboardType) -> Any? {

              was written, in order to avoid particular nastiness, you can't just make a copy of the root object, otherwise you wind up in the balancing init method:

              public required init?(pasteboardPropertyList propertyList: Any, ofType type: NSPasteboard.PasteboardType) {

              with the object that was just inited (self) and the copy of a useless object of the same class. You have to transfer, by hand, all of the properties. You have to transfer those properties under any circumstances.

              personally I'd rather use a copy method. not allowed here.

               

              what I settled on was making a dictionary, one with all of the properties, for the base object. (subObjects can be left intact, just duplicated in the base dictionary.) then coding it into a Data object, and returning that. Then on init, copying the properties, and in the cases of reference types, just moving them - from the dictionary to the newly minted object.  It's an entirely pointless hassle I could do without. Some of those subObjects are interconnected, and I have to reconnect the duplicates, by hand as they are copied.

               

              I thought I had run into a reason you can't simply copy objects relatively early in my process. But I've forged ahead in the meantime, and I "currently" have a solution that "should" work. I'll put down supporting a "copy" protocol on the list for refactoring. at some point in the future.