On Feb 13, 2015, at 2:08 PM, Quincey Morris < email@hidden> wrote:
It seems to me that the outcomes you’ve described are what would be expected, except in a couple of details.
On Feb 13, 2015, at 12:17 , Mike Ellard <email@hidden> wrote:
What I would expect:
A) Swift would not expose alloc or `new` at all. There shouldn’t be a way to create objects without going through an initializer.
I don’t know why you included ‘new’ in here. It’s valid to use it as a factory method in a subclass of NSObject, and I assume the behavior you’re seeing comes from Swift treating it as a factory method because of its name. As you showed, it doesn’t *not* go through an initializer. I don’t see how Swift could disallow it.
Part of the problem with `new` is that it is a shorthand for alloc and init. This is fine in Objective-C, where every subclass of NSObject inherits a valid init method. However, in Swift, initializers are not inherited if a subclass adds new, non-optional properties. So a Swift class may not have a valid argumentless initializer. If you hit a case like this, which is probably quite common, `new` will cause a runtime error.
You can see the Playground that I just attached to Radar 19834469 for an example of this. B) If a class does override alloc (either in Swift in or a mixed Objective-C / Swift project), then initializing an object would call the overridden alloc method.
This is the one that’s a bit puzzling. There are frameworks classes (such as NSArray IIRC) that return a placeholder object from ‘alloc’ and do their actual memory allocation in ‘init’, and creating such objects in Swift would break (or would they?) if Swift used an object creation methodology that didn’t do alloc/init in the Obj-C way.
I’m not saying that there shouldn’t be underlying alloc and `new` methods in the Objective-C classes. Obviously, those have to be there. However, not everything in Objective-C needs to be exposed in Swift. For example, all of the performSelector variants are not exposed in Swift. They’re still there in Objective-C, but Swift doesn’t give developers an easy way to use / misuse them. The same thing could be done with alloc and `new`. In Swift, they could be internal methods rather than public ones.
It’s possible that Swift alloc/inits Obj-C-style objects in the Obj-C-normal way, but that alloc and init overrides don’t produce the same runtime class structure as the corresponding Obj-C overrides.
I think your test needs to be a bit more intricate. What happens if you subclass NSObject in Obj-C with an alloc override, then sub-subclass that in Swift, also with an alloc override. Which, if any, allocs are invoked in that case?
Similarly, what happens if you subclass NSObject in Swift with an alloc override, then instantiate that class in Obj-C using the standard alloc/init sequence? (You could sub-subclass in Obj-C for parallelism, if you wanted, but I suspect the simpler test will suffice.)
The additional tests you’ve suggested are interesting. They would provide interesting additional material for Radar 19830571, and perhaps a couple of new Radars as well. I will run them if I have a chance to do so.
C) That in Swift, the NSObject alloc method would be “final” so that it couldn’t be overridden.
As before, I’m not sure why you would want this. If Swift and Obj-C are to be interoperable, doing the override in Swift ought to be possible, even if for other reasons it only executed when an instance was created from the Obj-C side.
To be honest, I don’t want it. I think it would be much better if alloc were not exposed to Swift at all.
However, if it is the case that A) alloc needs to be exposed to support a particular functionality, and B) overrides of alloc are not called when initializing objects, and therefore don’t really do anything, then C) I would want alloc to marked as final so that it’s clear that you can’t really subclass it in Swift for any useful purpose.
So the simple solution is to not expose alloc in Swift. If alloc must be exposed and cannot effectively be overridden, then marking it as final seems like a logical thing to do.
Sincerely,
Michael Patrick Ellard
|