Skip to content

Commit 7a66c6e

Browse files
committed
[docs] Record some of the known problems with Swift's initializer model.
...in the hopes that this will guide future proposals and evolution.
1 parent 44f71b1 commit 7a66c6e

File tree

1 file changed

+106
-0
lines changed

1 file changed

+106
-0
lines changed

docs/InitializerProblems.rst

Lines changed: 106 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,106 @@
1+
:orphan:
2+
3+
.. title:: Problems with Initializers
4+
5+
6+
Problem 1: Initializers are complicated
7+
=======================================
8+
9+
By formalizing Objective-C's initialization conventions, we've ended up with a
10+
tower of complexity where users find it easier to do the wrong thing and then
11+
follow the compiler fix-its. I [Jordan R] still feel like the individual rules
12+
aren't so complicated:
13+
14+
| Designated initializers chain.
15+
| Designated initializers are inherited if (a) there are no manual
16+
initializers, and (b) all properties have initial values.
17+
18+
| Convenience initializers delegate.
19+
| Convenience initializers are inherited if all of the superclass's
20+
designated initializers are present.
21+
22+
| If you want to call an initializer on a dynamic type, it must be marked
23+
required.
24+
| Protocols are one way to do this, so initializers that satisfy protocol
25+
requirements must be required.
26+
| If your superclass has a required initializer, you must provide it
27+
somehow.
28+
29+
but
30+
31+
"When even Andy Matuschak and Rob Rix can't understand your model, you have
32+
a problem." - Joe Groff
33+
34+
35+
Problem 2: Convenience initializers are missing use cases
36+
=========================================================
37+
38+
With all our rules, we actually rule out some important use cases, like this one on NSDocument:
39+
40+
The ``init`` method of NSDocument is the *designated initializer,* and it is
41+
invoked by the other initializers ``initWithType:error:`` and
42+
``initWithContentsOfURL:ofType:error:``. If you perform initializations that
43+
must be done when creating new documents but not when opening existing
44+
documents, override ``initWithType:error:``. If you have any initializations
45+
that apply only to documents that are opened, override
46+
``initWithContentsOfURL:ofType:error:``. If you have general
47+
initializations, override ``init``. In all three cases, be sure to invoke
48+
the superclass implementation as the first action.
49+
50+
-- `Document-Based App Programming Guide for Mac`__
51+
52+
__ https://developer.apple.com/library/mac/documentation/DataManagement/Conceptual/DocBasedAppProgrammingGuideForOSX/ManagingLifecycle/ManagingLifecycle.html#//apple_ref/doc/uid/TP40011179-CH4-SW11
53+
54+
Because we don't allow overriding convenience initializers with other
55+
convenience initializers, there's nowhere to perform post-customization of
56+
NSDocuments for each particular case.
57+
58+
59+
Problem 3: Factory Initializers
60+
===============================
61+
62+
Finally, we try to standardize on initializers for object creation in Swift,
63+
even going as far as to import Objective-C factory methods as initializers…but
64+
there are some patterns that cannot be written in Swift, such as this one::
65+
66+
class AnyGenerator<Element> : GeneratorType {
67+
init<
68+
WrappedGenerator: GeneratorType
69+
where
70+
WrappedGenerator.Element == Element
71+
>(wrapped: WrappedGenerator) -> AnyGenerator {
72+
return AnyGeneratorImpl(wrapped)
73+
}
74+
// other generator stuff
75+
}
76+
77+
class AnyGeneratorImpl<WrappedGenerator: GeneratorType> :
78+
AnyGenerator<WrappedGenerator.Element> {
79+
var wrapped: WrappedGenerator
80+
init(wrapped: WrappedGenerator) {
81+
self.wrapped = wrapped
82+
}
83+
// other generator stuff
84+
}
85+
86+
We ended up making ``AnyGenerator`` a struct that wraps ``AnyGeneratorImpl`` to
87+
get around this, but it's not a nice solution.
88+
89+
90+
Solutions?
91+
==========
92+
93+
We've had a number of ideas for improving the state of the world, including
94+
95+
- Allow designated initializers to delegate to other designated initializers
96+
(using static dispatch). This makes convenience initializers a niche feature.
97+
98+
- Add the concept of factory initializers, which don't promise to return
99+
``Self``. These are either never inherited or must always be overridden in a
100+
subclass.
101+
102+
- Allow convenience initializers to chain to superclass convenience
103+
initializers. This isn't strictly safe, but it permits the NSDocument idiom.
104+
105+
None of these solve all the initializer problems listed above on their own, and
106+
we'd want to be careful not to *increase* complexity in this space.

0 commit comments

Comments
 (0)