Objective-C/SmalltalkThese are the rules for initializers in Smalltalk and Objective-C:
- An "initializer" is a normal method and a normal message send.
- There is no second rule.
new) to the class? No there isn't, it's just a convenient and obvious place to put it since we don't have the instance yet and the class exists and is an obvious place to go to for instances of that class. However, we could just as well ask a different class to create the object for us.
The same goes with calling
super. Yes, that's usually
a good idea, because usually you want the superclass's behavior,
but if you don't want the superclass's behavior, then don't call.
Again, this is not a special rule for initializers, it usually
follows from what you want to achieve. And sometimes it doesn't, just
like with any other method you override: sometimes you call
sometimes you do not.
The same goes for assigning the return value, doing the
self=[super init]; dance. Again, this is not
at all required by the language or the frameworks, although
apparently it is a common misconception that it is, a
misconception that is, IMHO, promoted by careless creation
of "best practices" as "immutable rules", something I wrote
about earlier when talking about the useless typing out of the
id type in method declarations.
However, returning self and using the returned value is a useful
convention, because it makes it possible for
methods to return a different object than what they started
with (for example a specific subclass or a singleton).
Swift initializersApple's new Swift language has taken a page from the C++ and Java playbooks and made initialization a special case. Well, lots of special cases actually. The Swift book has 30 pages on initialization, and they aren't just illustration and explanation, they are dense with rules and special cases. For example:
- You can set a default value of a property in the variable definition.
- Or you can set the default value in an initializer.
- Designated initializers are now a first class language construct.
- Parameterized initializers have local and external parameter names, line methods.
- Except that the first parameter name is different and so Swift automatically provides and external parameter name for all arguments, which it doesn't with methods.
- Constant properties aren't constant in initializers.
- Swift creates a default initializer for both classes and structs.
- Swift also creates a default member wise initializer, but only for structs.
- Initializers can (only) call other initializers, but there are special rules for what is and is not allowed and these rules are different for structs and classes.
- Providing specialized initializers removes the automatically-provided default initializers.
- Initializers are different from other methods in that they are not inherited, usually.
- Except that there are specific circumstances where they are inherited.
- Confused yet? There's more!
- If your subclass provides no initializers itself, it inherits all the superclass's initializers
- If your subclass overrides all the superclass's designated initializers, it inherits all the convenience initializers (that's also a language construct). How does this not break if the superclass adds initializers? I think we've just re-invented the fragile-base-class problem.
- Oh, and you can initialize instance variables with the values returned by closures or functions.
Particularly, it is not possible to substitute a different value
nil to indicate failure to initialize, nor
is it possible to call other methods (as far as I can tell).
To actually provide these useful features, we need something else:
- Use the Factory method pattern to actually do the powerful stuff you need to do ...
- ...which gets you back to where we were at the beginning with Objective-C or Smalltalk, namely sending a normal message.
So with all due respect to Michael A. Jackson:
First rule of baking programming conventions into the language: Don't do it!
The second rule of baking programming conventions into the language (experts only): Don't do it yet!