File: secondary-constructors.md

package info (click to toggle)
kotlin 1.3.31%2Bds1-3
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 109,908 kB
  • sloc: java: 454,756; xml: 18,599; javascript: 10,452; sh: 513; python: 97; makefile: 69; ansic: 4
file content (134 lines) | stat: -rw-r--r-- 4,006 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
# Secondary constructors

## Goal

Compatibility with Java hierarchies that demand multiple constructors, such as
- Android Views
- Swing dialogs

## Examples

With a primary constructor:
``` kotlin
class Foo(a: Bar): MySuper() {
  // when there's a primary constructor, (direct or indirect) delegation to it is required
  constructor() : this(Bar()) { ... } // can't call super() here
  constructor(s: String) : this() { ... }
}
```

No primary constructor:
``` kotlin
class Foo: MySuper { // initialization of superclass is not allowed
  constructor(a: Int) : super(a + 1) { ... } // must call super() here
}
```

No primary constructor + two overloaded constructors
``` kotlin
class Foo: MySuper { // initialization of superclass is not allowed
  constructor(a: Int) : super(a + 1) { ... }
  constructor() : this(1) { ... } // either super() or delegate to another constructor
}
```

## TODO

- [ ] is delegation allowed when no primary constructor is present?
- [ ] Allow omitting parameterless delegating calls?

## Syntax for primary constructor

- There's a primary constructor if
  - parentheses after class name, or
  - there're no secondary constructors (default primary constructor)
- No parentheses after name and an explicit constructor present => no primary constructor

No primary constructor => no supertype initialization allowed in the class header:
``` kotlin
class Foo : Bar() { // Error
  constructor(x: Int) : this() {}
}
```

When a primary constructor is present, explicit constructors are called *secondary*.

Every class **must** have a constructor. The following is an error:
``` kotlin
class Parent
class Child : Parent { }
```
The error is: "superclass must be initialized". This class has a primary constructor, but does not initialize its superclass in the class header.
## Syntax for explicit constructors

```
constructor
  : modifiers "constructor" valueParameters (":" constructorDelegationCall) block
  ;
  
constructorDelegationCall
  : "this" valueArguments
  | "super" valueArguments
  ;
```

Passing lambdas outside parentheses is not allowed in `constructorDelegationCall`.

## Rules for delegating calls

The only situation when an explicit constructor may not have an explicit delegating call is
- when there's no primary constructor **and** the superclass has a constructor that can be called with no parameters passed to it

``` kotlin
class Parent {}
class Child: Parent {
  constructor() { ... } // implicitly calls `super()`
}
```

If there's a primary constructor, all explicit constructors must have explicit delegating calls that (directly or indirectly) call the primary constructor.

``` kotlin
class Parent {}
class Child(): Parent() {
  constructor(a: Int) : this() { ... }
}
```

## Initialization code outside constructors

The primary constructor's body consists of
- super class initialization from class header
- assignments to properties from constructor parameters declared with `val` or `var`
- property initializers and bodies of anonymous initializers following in the order of appearance in the class body

If the primary constructor is not present, property initializers and anonymous initializers are conceptually "prepended" to the body 
of each explicit constructor that has a delegating call to super class, and their contents are checked accordingly for definite
initialization of properties etc.

## Syntax for anonymous initializers

Anonymous initializer in the class body must be prefixed with the `init` keyword, without parentheses:

``` kotlin
class C {
  init {
    ... // anonymous initializer
  }
}
```

## Checks for constructors

All constructors must be checked for
- absence of circular delegation
- overload compatibility
- definite initialization of all properties that must be initialized
- absence of non-empty super call for enum constructors

No secondary constructors can be declared for
- traits
- objects (named, anonymous, and default)
- bodies of enum literals

Data classes should have a primary constructor