С нуля до распределенных приложений.
Scala гибридный функциональный/ОО язык и обладает одним из самых мощных аппаратов по работе с классами и типами. Создатель языка, Мартин Одерски - автор generics в языке Java.
Синтаксис создания классов:
class MyClass extends SomeBaseClass { }
// создание объекта
new MyClass()
Тело класса является основным конструктором. Все поля и функции объявленные в нем являются членами объектов класса.
class Vector2D(x: Double, y: Double) {
val length = Math.sqrt(x * x + y * y)
println("Created class") // вызовется каждый раз при создании объекта
}
Дополнительные конструкторы объявляются функциями с названием this и должны вызывать основной конструктор:
class Vector2D(x: Double, y: Double) {
val length = Math.sqrt(x * x + y * y)
def this(l: Double) = this(l, 0)
}
В Scala доступны обычные модификаторы доступа для полей класса:
Кроме того, модификаторы могут быть расширены квалификаторами [this] или [X]. Первый ограничивает доступ до одного объекта, второй делает поле видимым всем включающим классам или пакетам до X.
package mypackage {
package subpackage {
class MyClass {
private val privateField = 1
private[this] val morePrivateField = 2
// видимо всем классам объектам внутри subpackage
private[subpackage] val lessPrivateField = 3
def add(that: MyClass) = this.privateField + that.privateField
// ошибка комплияции
def addMore(that: MyClass) = this.morePrivateField + that.morePrivateField
}
}
}
Все поля классов по умолчанию имеют модификатор public.
Сделано это тех соображений, что Scala ориентирована на использование неизменяемых значений, поэтому “утечка” поля класса в интерфейс не дает возможности сломать программу, а только облегчает тестирование.
Параметры конструкторов имеют по умолчанию модификатор private[this]. Для превращения их в поле класса надо добавить в объявление ключевое слово val/var.
class MyClass(val x: Int, y: Int) { }
x - имеет модификатор public, y - имеет модификатор private[this]
Несколько операций в Scala вызывают методы с определенным названием в классе. Оператор == вызванный на объекте класса вызывает метод equals, а ( ) метод apply.
class MyNumber(x: Double) {
override def equals(other: Any) = true
def apply() = println(x)
def apply(n: Int) = println(x * n)
}
val n1 = new MyNumber(20.4)
println(n1 == 20) // true
n1() // 20.4
n1(10) // 204.0
В Scala нет статических (static) методов, но есть особый синтаксис для создания объектов-синглтонов.
object MyObject {
val myField = 1
def myPrint = println(myField)
}
Этот объект будет создан в единственном экземпляре и доступен в любое время. Их можно использовать как объекты некоторого класса, для этого достаточно указать, что они унаследованы от него ключевым словом extends.
class MyNumber(val x: Int) {}
object MyZero extends MyNumber(0) {}
def printNumber(n: MyNumber) = {
println(n.x)
}
printNumber(MyZero) // 0}
Для каждого класса можно объявить специальный объект-компаньон (companion object). Это объект объявленный в том же файле и с тем же именем, что и класс. Этот объект имеет доступ к private полям класса.
Возможно вы уже встречались с созданием некоторых объектов без использования ключевого слова new. Здесь нет магии, это вызов метода apply на объекте-компаньоне.
class Person(val firstName: String, val middleName: String, val lastName: String) {}
object Person {
def apply(firstName: String, lastName: String) = new Person(firstName, "", lastName)
def apply(firstName: String) = new Person(firstName, "", "")
}
val p = Person("Tagir", "Magomedov")
Часто дополнительные конструкторы класса объявляют именно так.