You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: sips/pending/_posts/2016-01-11-static-members.md
+37-10
Original file line number
Diff line number
Diff line change
@@ -4,9 +4,9 @@ title: SIP 25 - @static fields and methods in Scala objects(SI-4581)
4
4
disqus: true
5
5
---
6
6
7
-
__Dmitry Petrashkoand Sébastien Doeraene__
7
+
__Dmitry Petrashko, Sébastien Doeraene and Martin Odersky__
8
8
9
-
__first submitted TODO 2016__
9
+
__first submitted 11 January 2016__
10
10
11
11
## Motivation ##
12
12
@@ -18,18 +18,19 @@ Some JVM and JavaScript frameworks require classes to have specific static field
18
18
19
19
For example, classes extending `android.os.Parcelable` are required to have a static field named `CREATOR` of type `android.os.Parcelable$Creator`.
20
20
21
-
Another example is using an [`AtomicReferenceFieldUpdater`](http://docs.oracle.com/javase/7/docs/api/java/util/concurrent/atomic/AtomicReferenceFieldUpdater.html).
21
+
Another example is using an [`AtomicReferenceFieldUpdater`](http://docs.oracle.com/javase/8/docs/api/java/util/concurrent/atomic/AtomicReferenceFieldUpdater.html).
22
22
23
23
On the JavaScript side, one example is [Relay Route Definitions](https://facebook.github.io/relay/docs/guides-routes.html), whose subclasses must define static fields such as `queries`.
24
24
Static methods and fields for JavaScript classes are one of the very few things (if not the only thing) that Scala.js "cannot do" at the moment, at least not declaratively.
25
25
26
26
## Overview ##
27
27
28
-
In order for method or field to be considered static it needs to be defined in an `object` and annotated `@static`.
28
+
In order for a method or field to be considered static it needs to be defined in an `object` and annotated `@static`.
29
29
There is no special syntax proposed to access these members, they are accessed as if they were a member of defining objects with all appropriate access requirements for accessing them.
30
30
31
31
For example:
32
32
33
+
```scala
33
34
{% highlight scala %}
34
35
classFoo
35
36
@@ -41,10 +42,12 @@ object Foo {
41
42
println(Foo.x)
42
43
println(Foo.bar(12))
43
44
{% endhighlight %}
45
+
```
44
46
45
-
Intuively, the presence of the `@static` annotation ensures that a field/method is declared as a static member of the companion class.
47
+
Intuitively, the presence of the `@static` annotation ensures that a field/method is declared as a static member of the companion class.
46
48
For the JVM, the above would therefore look to other Java code as if it had been declared with the following Java code:
47
49
50
+
```java
48
51
{% highlight java %}
49
52
classFoo {
50
53
publicstaticint x =5;
@@ -53,10 +56,12 @@ class Foo {
53
56
}
54
57
}
55
58
{% endhighlight %}
59
+
```
56
60
57
61
In Scala.js, the `@static` annotation has no semantic effect in Scala objects, as they are not visible from JavaScript anyway (it could be used for optimizations).
58
62
It has a semantic effect on Scala.js-defined JS classes, for example:
59
63
64
+
```scala
60
65
{% highlight scala %}
61
66
@ScalaJSDefined
62
67
classFooextends js.Object
@@ -67,9 +72,11 @@ object Foo extends js.Object {
67
72
@static defbar(y: Int):Int= x + y
68
73
}
69
74
{% endhighlight %}
75
+
```
70
76
71
77
would look to JavaScript code as if it had been declared with the following JavaScript code:
72
78
79
+
```javascript
73
80
{% highlight javascript %}
74
81
classFooextendsObject {
75
82
staticbar(y) {
@@ -78,22 +85,42 @@ class Foo extends Object {
78
85
}
79
86
Foo.x=5; // in ES6, there is no declarative syntax for static fields yet
80
87
{% endhighlight %}
88
+
```
89
+
90
+
## Comparison with mirror classes ##
91
+
92
+
Scalac currently generates static forwarders for fields and methods in top-level objects:
93
+
94
+
```scala
95
+
{% highlight scala %}
96
+
objectO {
97
+
vald=1
98
+
objectI {
99
+
valf=1
100
+
}
101
+
}
102
+
{% endhighlight %}
103
+
```
104
+
105
+
Under the proposed scheme users will be able to opt-in to have the field `f` defined in the inner object `I` emited as a static field.
106
+
In case `O.d` is annotated with `@static` the field will be crated as a static field `d` in `class O`.
107
+
If not annotated, it will be created in the companion module with a static forwarder `d` in `class O`.
81
108
82
109
## Restrictions ##
83
110
84
-
The following rules ensure that method can be correctly compiled into static member on both JVM and JavaScript:
111
+
The following rules ensure that methods can be correctly compiled into static members on both JVM and JavaScript:
85
112
86
113
1. Only objects can have members annotated with `@static`
87
114
88
115
2. The fields annotated with `@static` should preceed any non-`@static` fields. This ensures that we do not introduce surprises for users in initialization order.
89
116
90
-
3. The right hand side of a method or field annotated with `@static` can only refer to members of globally accessible objects and `@static` members. In particular, for non-static objects `this` is not accesible. `super` is never accessible.
117
+
3. The right hand side of a method or field annotated with `@static` can only refer to top-level classes, members of globally accessible objects and `@static` members. In particular, for non-static objects `this` is not accesible. `super` is never accessible.
91
118
92
119
4. If a member `foo` of an `object C` is annotated with `@static`, the companion class `C` is not allowed to define term members with name `foo`.
93
120
94
121
5. If a member `foo` of an `object C` is annotated with `@static`, the companion class `C` is not allowed to inherit classes that define a term member with name `foo`.
95
122
96
-
6. Only @static methods and vals are supported in companions of traits. Java8 supports those, but not vars, and JavaScript does not have interfaces at all.
123
+
6. Only `@static` methods and vals are supported in companions of traits. Java8 supports those, but not vars, and JavaScript does not have interfaces at all.
97
124
98
125
## Compilation scheme ##
99
126
No modificaiton of the typer is planned. The current proposed scheme piggybacks on already existing scoping restrictions in the typer, thus requiring `@static` methods to be defined in `objects`.
@@ -103,14 +130,14 @@ If implemented in the dotty code base, the following modifications would be need
103
130
- extend `LambdaLift` to trigger an error if a method annotated with `@static` method cannot be lifted to the top level scope;
104
131
- extend `GenBCode` to emit static fields and methods in companion classes and forwarders to them in companion modules.
105
132
106
-
## Overriding&Hiding ##
133
+
## Overriding & Hiding ##
107
134
Java allows classes to define static methods with the same name and signature as a static method of a superclass. In order to define the semantics of such cases, the Java Specification introduces the notion of [hiding](http://docs.oracle.com/javase/specs/jls/se8/html/jls-8.html#jls-8.4.8.2).
108
135
109
136
This is required because in Java calling a `static` method on a class instance is supported.
110
137
This proposal does not need to introduce this notion as we do not support such calls.
111
138
112
139
## Comparison with [@lrytz's proposal](https://gist.github.com/lrytz/80f3141de8240f9629da) ##
113
-
Lucas Rytz has proposed a similar SIP, but his SIP requires changes to the typer to ensure that `@static` fields do not capture `this`, as in his proposal `@static` fields are defined in the class, rather than its companion object.
140
+
Lukas Rytz has proposed a similar SIP, but his SIP requires changes to the typer to ensure that `@static` fields do not capture `this`, as in his proposal `@static` fields are defined in the class, rather than its companion object.
114
141
It also does not address the question of `@static` members in inner objects and inheritance/hiding of those methods in subclasses.
0 commit comments