class init question

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 })

????

Replies

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"

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.