-
Notifications
You must be signed in to change notification settings - Fork 0
Class
class ::=
[<annotations>]
<class_modifiers> <class | object | trait | enum | struct | package object>
[className]¹ [<generics>] [(<constructor_field>, [<constructor_field>, ...])]²
[extends superClass[(<call_parameters>)]³ [with superTrait1 [with superTrait2 ...]] ]⁴ [{
<enum_constant>⁵
...
<class_statement>
...
}]
class_modifiers ::= [private | public]⁶ [stub] [case⁷ | abstract | final]//in any order
enum_constant ::= name(<call_parameters>)
class_statement ::= <class_field> | <definition>
call_parameters ::= [<call_parameter>[, <call_parameter> ...]]
call_parameter ::= [parameterName = ] <\expression>
- The name should be omitted for a package object.
- The class constructor. Traits cannot contain constructors. Constructor can be only one. As alternative constructors you can use an apply function.
- Class can extend only one class and must set the constructor parameters of the superclass if it is necessary.
- Class can extend many traits. Traits have no constructor.
- The list of constants for enum class.
- Default visibility is public. Private classes are visible only inside the file.
- Case classes are immutable classes. The equals and hash functions will be auto generated according to constructor fields.
constructor_field ::= <constructor_field_modifiers> [val | var]¹ name [: <datatype>]² [= <expression>]³
constructor_field_modifiers ::= [<visibility>]⁴ [override] [weak]⁵_//in any order_
-
You can use val or var modifiers to declare a class field. Otherwise the value of the constructor field would be available only for definition other class fields.
-
Data type of the parameter could be omitted when you use the default value.
-
Default expression for the constructor field.
-
Default visibility is public.
-
Use weak reference to avoid retain cycle in Objective-C.
class Foo(val bar : int, val p = 0)
class_field ::= <field_modifiers> <val | var>¹ name [: <datatype>]² [= <expression>]³
field_modifiers ::= [<visibility>]⁴ [lazy]⁵ [volatile]⁶ [override] //in any order
visibility ::= private | protected | public
¹ - val - immutable, var - mutable
² - data type of the field could be inferred using the expression, so it's possible to omit it
³ - expression for initial value of the field. It could be omitted only for an optional data type
⁴ - default visibility is public
⁵ - lazy fields are calculated at the time of a first call
⁶ - put the memory barrier after changing of the field to guarantee the order of operations
val foo : int = 0
lazy val bar = foo*foo
definition ::= [<annotations>] <def_modifiers> def name[<generics>][([<self_parameter>, ]<parameter>[, <parameter>...])] <[: <datatype>]¹ [= <expression>]² | {<expressions>}³>
def_modifiers ::= [<visibility>]⁴ [final]⁵ [override]⁶ [static]⁷ [inline]⁸ //in any order
¹ - data type of the definition could be inferred using the expression, so it's possible to omit it
² - expression could be omitted for abstract functions
³ - to create a procedure you have to use braces without equal sign
⁴ - default visibility is public
⁵ - prohibit overriding of the function
⁶ - it's necessary to put this modifier when you override or implement the function
⁷ - static modifier would be removed soon. It's better to use objects.
⁸ - inline the code of the function in places of call. It's useful to reduce number of function calls and to avoid creation of lambdas.
def square(x : int) = x*x
def square(x : int) : int = x*x
def procedure(x : int) {
log("x = $x")
}
parameter ::= [weak]¹ name [: <datatype>]² [= <expression>]³
¹ - this works only with lambdas. It's necessary to avoid memory leaks in Objective-C. When you save a block in a field, it's possible that the block will retain an object. This situation can lead to retain cycle. This modifier replaces direct call of class fields or functions with call using a weak reference.
² - data type of the parameter could be omitted when you use the default value.
³ - default value of the parameter. If you don't point a value of the parameter in a call, the default value will be used.
def foo(f : int -> int, bar = 1)
self_parameter ::= self : <datatype>
if the class contains generics you can define a function for the particular type of the generic using this construction. You can also define generics of the function using generic of the class.
class Foo<X>(val bar : [X]) {
def flat<Y>(self : Foo<[Y]>) : [Y] = {
val arr = ArrayBuilder<Y>()
bar.for{ys ->
ys.cast<[Y]>.for{y ->
arr.append(y)
}
}
arr.build
}
}
val foo = Foo<[int]>([[1, 0], [3]])
assertEquals([1, 0, 3], foo.flat)
generics ::= < <generic> [, <generic> ...] >
generic ::= name [ extends super1 [with super2 [with super3 ...]]