Skip to content

Commit e58a7f5

Browse files
author
Eli Friedman
committed
First draft of docs on classes.
Swift SVN r2571
1 parent 1b51012 commit e58a7f5

File tree

1 file changed

+194
-0
lines changed

1 file changed

+194
-0
lines changed

docs/classes.rst

+194
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,194 @@
1+
Swift classes in detail
2+
=======================
3+
4+
Syntax overview
5+
---------------
6+
7+
::
8+
9+
class MyClass {
10+
var MyVar : Int
11+
func f(x : Int) -> Int {
12+
return MyVar + x
13+
}
14+
static fund getAMyclass() -> MyClass {
15+
return new MyClass
16+
}
17+
constructor() {
18+
MyVar = 10
19+
}
20+
destructor {
21+
// Misc finalization
22+
}
23+
}
24+
25+
extension MyClass {
26+
func g() -> Int {
27+
return 4
28+
}
29+
}
30+
31+
func f() {
32+
var x = new MyClass(10)
33+
}
34+
35+
class MyDerived : MyClass {
36+
func h() {}
37+
}
38+
39+
40+
Constructing an instance of a class
41+
-----------------------------------
42+
::
43+
44+
var x = new MyClass(10)
45+
46+
This syntax basically just calls the constructor found by overload resolution
47+
on the given class.
48+
49+
FIXME: There's been some debate whether we should allow default construction
50+
of classes, or constructing a class with ``MyClass(10)`` on an opt-in basis.
51+
We might want to take another look here later.
52+
53+
Inheritance
54+
-----------
55+
56+
A class inherits from at most one other class.  The base class is named in
57+
the same place protocols are named. All member functions/properties of the
58+
base class can be accessed through an instance of the derived class
59+
(ignoring access control and shadowing).
60+
61+
Constructors
62+
------------
63+
::
64+
65+
constructor() {
66+
MyVar = 10
67+
}
68+
69+
This syntax defines a constructor, which is called to build an instance of
70+
the object.
71+
72+
If no constructors are defined, an implicit constructor is defined which
73+
takes no arguments and implicitly initializes all ivars and the base class.
74+
75+
A constructor in the derived class must delegate to a constructor in the
76+
base class.
77+
78+
The exact syntax for initialization of ivars/delegation to the base class
79+
is still sort of an open question. There are a few possible models here:
80+
81+
1. All ivars are implicitly initialized before the body of the constructor.
82+
Initializers can be provided on the ivar directly if necessary. This is the
83+
closest to the current model. This was discarded sucks because it doesn't
84+
allow initialization based on
85+
arguments.
86+
2. Some sort of C++-style list of initializers; this was discarded quickly
87+
during discussion as being both ugly and not as flexible as we would like.
88+
3. Add some sort of init block to constructors, like::
89+
90+
constructor (x : Int) {
91+
init {
92+
myIvar = x
93+
}
94+
print(myIvar)
95+
}
96+
97+
Capturing self in the init block would be banned. If an ivar is accessed
98+
before initialization, or not initialized in the init block, it would be
99+
automatically "default"-initialized (as-if with an empty argument list) if
100+
such construction is possible, or an error otherwise. The ivar rules would
101+
be enforced using CFG analysis. Delegation to the base class would be in
102+
the init block; the syntax here is also an open question. Proposals
103+
included ``super(1,2)``, ``constructor(1,2)``, ``This(1,2)``,
104+
``MyBaseClass(1,2)``. In the delegation case, the init block would not
105+
access ``self`` at all, and would perform a delegation call at the end
106+
(syntax also undecided).
107+
108+
This approach sucks simply because it's ugly. There are a couple of
109+
alternative ways to express this, including some sort of explicit
110+
``constructed`` marker, but I'm not sure we can come up with a variant
111+
which isn't ugly.
112+
113+
4. Implicitly deduce an init block using the CFG::
114+
115+
constructor (x : Int) {
116+
// init implicitly begins here
117+
myIvar = x
118+
// init implicitly ends here
119+
myMethod()
120+
}
121+
122+
Essentially the same semantic rules as (2), but less ugly (and possibly
123+
slightly more flexible in the presence of control flow because there
124+
could be multiple end-points). The downside here is that it isn't obvious
125+
at a glance where exactly the split occurs, which could lead to unexpected
126+
default construction.
127+
128+
Destructors
129+
-----------
130+
131+
A destructor is defined using just the keyword destructor followed by a
132+
brace-stmt. Destructors can only be defined in classes, and only in the
133+
class declaration itself. It's a runtime error if the body resurrects the
134+
object (i.e. if there are live reference to the object after the body of
135+
the destructor runs). Member ivars are destroyed after the body of the
136+
destructor runs. FIXME: Where exactly do we run the base class destructor?
137+
138+
Member functions and properties
139+
-------------------------------
140+
141+
Like structs, classes have member functions, properties, and ivars.
142+
Unlike structs, member functions and properties are overridable (and use
143+
dynamic dispatch) by default. Overriding can be disabled with the "final"
144+
attribute.
145+
146+
In a derived class, if you define a member with the same name as a member
147+
of its base class, the base class member is overridden by default.  If the
148+
type doesn't match (what exactly "match" means TBD), it's an error.  This
149+
implies that it's impossible to hide a base class member without explicit
150+
markings.
151+
152+
The override-by-default model requires two attributes to control when it
153+
isn't doing the right thing: "shadow" and "overload".  "overload" means
154+
that the member of the derived class is an overload of the base class member;
155+
all the members from the base class and the derived class are part of overload
156+
resolution.  "shadow" means that the derived class is intentionally shadowing
157+
the base class name; the name from the base class is never found by name lookup
158+
on the derived class.
159+
160+
Accessing overridden members of the base class
161+
----------------------------------------------
162+
163+
Tentatively, ``super.foo()`` accesses foo from the base class, bypassing
164+
dynamic dispatch.
165+
166+
Extensions
167+
----------
168+
169+
Extensions for structs can only contain methods, properties,
170+
and constructors. They always use static dispatch.
171+
172+
Extensions for classes are more flexible in two respects:
173+
174+
1. They can contains ivars: these are essentially baking in language support
175+
for a side-table lookup. They must be either default-initializable or have
176+
an explicit initializer on the variable definition. The initializer is run
177+
lazily.
178+
2. Members of extensions of classes can be overridden (?).  Per our discussion
179+
in the meeting, I thought this model could work, but in retrospect it might
180+
be way too confusing; if you have a base class X and a derived class Y,
181+
overriding an extension of X in an extension of Y leads to strange behavior
182+
depending on whether the extension of Y is loaded (essentially, the same
183+
weirdness of ObjC categories and linking).
184+
185+
Name lookup for extensions works much the same way that it does for a derived
186+
class, except that rather than base class vs. derived class, it's names from
187+
current extension vs. names from other sources (or something similar to this).
188+
If there's multiple declarations with the same name, it's an error, and the
189+
user has to resolve it with "shadow", and "overload" (where "shadow" only works
190+
for names from other modules; we'll want some other mechanism for name remapping
191+
for protocol implementations).
192+
193+
Constructors in extensions are required to delegate to another constructor. This
194+
is necessary because of access-control etc. (FIXME: implicit delegation?)

0 commit comments

Comments
 (0)