На этой странице мы расскажем об основах Scala.
Попробовать Scala в браузере.
Вы можете запустить Scala в браузере с помощью Scastie.
- Зайдите на Scastie.
- Вставьте
println("Hello, world!")
в левую панель. - Нажмите кнопку “Run”. Вывод отобразится в правой панели.
Это простой способ поэкспериментировать со Scala кодом без всяких настроек.
Большинство примеров кода в этой документации также интегрированы с Scastie, поэтому вы можете поэкспериментировать с ними, просто нажав кнопку Run.
Выражения
Выражения — это вычислимые утверждения.
1 + 1
Вы можете выводить результаты выражений, используя println
.
println(1) // 1
println(1 + 1) // 2
println("Hello!") // Hello!
println("Hello," + " world!") // Hello, world!
Значения
Результаты выражений можно присваивать именам с помощью ключевого слова val
.
val x = 1 + 1
println(x) // 2
Названные результаты, такие как x
в примере, называются значениями.
Вызов значения не приводит к его повторному вычислению.
Значения не изменяемы и не могут быть переназначены.
x = 3 // Не компилируется.
Типы значений могут быть выведены автоматически, но можно и явно указать тип, как показано ниже:
val x: Int = 1 + 1
Обратите внимание, что объявление типа Int
происходит после идентификатора x
, следующим за :
.
Переменные
Переменные похожи на значения константы, за исключением того, что их можно присваивать заново. Вы можете объявить переменную с помощью ключевого слова var
.
var x = 1 + 1
x = 3 // Компилируется потому что "x" объявлен с ключевым словом "var".
println(x * x) // 9
Как и в случае со значениями, вы можете явно указать тип, если захотите:
var x: Int = 1 + 1
Блоки
Вы можете комбинировать выражения, окружая их {}
. Мы называем это блоком.
Результат последнего выражения в блоке будет результатом всего блока в целом.
println({
val x = 1 + 1
x + 1
}) // 3
Функции
Функции — это выражения, которые принимают параметры.
Вы можете определить анонимную функцию (т.е. без имени), которая возвращает переданное число, прибавив к нему единицу:
(x: Int) => x + 1
Слева от =>
находится список параметров. Справа — выражение, связанное с параметрами.
Вы также можете назвать функции.
val addOne = (x: Int) => x + 1
println(addOne(1)) // 2
Функции могут принимать множество параметров.
val add = (x: Int, y: Int) => x + y
println(add(1, 2)) // 3
Или вообще не принимать никаких параметров.
val getTheAnswer = () => 42
println(getTheAnswer()) // 42
Методы
Методы выглядят и ведут себя очень похоже на функции, но между ними есть несколько принципиальных различий.
Методы задаются ключевым словом def
. За def
следует имя, список параметров, возвращаемый тип и тело.
def add(x: Int, y: Int): Int = x + y
println(add(1, 2)) // 3
Обратите внимание, как объявлен возвращаемый тип сразу после списка параметров и двоеточия : Int
.
Методы могут принимать несколько списков параметров.
def addThenMultiply(x: Int, y: Int)(multiplier: Int): Int = (x + y) * multiplier
println(addThenMultiply(1, 2)(3)) // 9
Или вообще ни одного списка параметров.
def name: String = System.getProperty("user.name")
println("Hello, " + name + "!")
Есть некоторые отличия от функций, но пока что их можно рассматривать как нечто похожее.
Методы также могут иметь многострочные выражения.
def getSquareString(input: Double): String = {
val square = input * input
square.toString
}
println(getSquareString(2.5)) // 6.25
def getSquareString(input: Double): String =
val square = input * input
square.toString
println(getSquareString(2.5)) // 6.25
Последнее выражение в теле становится возвращаемым значением метода (у Scala есть ключевое слово return
, но оно практически не используется).
Классы
Вы можете объявлять классы используя ключевое слово class
, за которым следует его имя и параметры конструктора.
class Greeter(prefix: String, suffix: String) {
def greet(name: String): Unit =
println(prefix + name + suffix)
}
class Greeter(prefix: String, suffix: String):
def greet(name: String): Unit =
println(prefix + name + suffix)
Возвращаемый тип метода greet
это Unit
, используется тогда, когда не имеет смысла что-либо возвращать. Аналогично void
в Java и C. Поскольку каждое выражение Scala должно иметь какое-то значение, то при отсутствии возвращающегося значения возвращается экземпляр типа Unit. Явным образом его можно задать как ()
, он не несет какой-либо информации.
Вы можете создать экземпляр класса, используя ключевое слово new
.
val greeter = new Greeter("Hello, ", "!")
greeter.greet("Scala developer") // Hello, Scala developer!
val greeter = Greeter("Hello, ", "!")
greeter.greet("Scala developer") // Hello, Scala developer!
Позже мы рассмотрим классы подробнее.
Классы-образцы (Case Class)
В Scala есть специальный тип класса, который называется классом-образцом (case class). По умолчанию такие классы неизменны и сравниваются по значению из конструктора. Вы можете объявлять классы-образцы с помощью ключевых слов case class
.
case class Point(x: Int, y: Int)
Можно создавать экземпляры класса-образца без использования ключевого слова new
.
val point = Point(1, 2)
val anotherPoint = Point(1, 2)
val yetAnotherPoint = Point(2, 2)
Они сравниваются по значению.
if (point == anotherPoint) {
println(s"$point and $anotherPoint are the same.")
} else {
println(s"$point and $anotherPoint are different.")
} // Point(1,2) и Point(1,2) одни и те же.
if (point == yetAnotherPoint) {
println(s"$point and $yetAnotherPoint are the same.")
} else {
println(s"$point and $yetAnotherPoint are different.")
} // Point(1,2) и Point(2,2) разные.
if point == anotherPoint then
println(s"$point and $anotherPoint are the same.")
else
println(s"$point and $anotherPoint are different.")
// Point(1,2) и Point(1,2) одни и те же.
if point == yetAnotherPoint then
println(s"$point and $yetAnotherPoint are the same.")
else
println(s"$point and $yetAnotherPoint are different.")
// Point(1,2) и Point(2,2) разные.
Есть еще много деталей, которые мы бы хотели рассказать про классы-образцы; мы уверены, что вы влюбитесь в них! Обязательно рассмотрим их позже.
Объекты
Объекты задаются и существуют в единственном экземпляре. Вы можете думать о них как об одиночках (синглтонах) своего собственного класса.
Вы можете задать объекты при помощи ключевого слова object
.
object IdFactory {
private var counter = 0
def create(): Int = {
counter += 1
counter
}
}
object IdFactory:
private var counter = 0
def create(): Int =
counter += 1
counter
Вы можете сразу получить доступ к объекту, ссылаясь на его имя.
val newId: Int = IdFactory.create()
println(newId) // 1
val newerId: Int = IdFactory.create()
println(newerId) // 2
Позже мы рассмотрим объекты подробнее.
Трейты
Трейты — как типы описывают характеристики классов, в нем могут объявляться определенные поля и методы. Трейты можно комбинировать.
Объявить трейт можно с помощью ключевого слова trait
.
trait Greeter {
def greet(name: String): Unit
}
trait Greeter:
def greet(name: String): Unit
Трейты также могут иметь реализации методов и полей, которые предполагается использовать умолчанию.
trait Greeter {
def greet(name: String): Unit =
println("Hello, " + name + "!")
}
trait Greeter:
def greet(name: String): Unit =
println("Hello, " + name + "!")
Вы можете наследовать свойства трейтов, используя ключевое слово extends
и переопределять реализацию с помощью ключевого слова override
.
class DefaultGreeter extends Greeter
class CustomizableGreeter(prefix: String, postfix: String) extends Greeter {
override def greet(name: String): Unit = {
println(prefix + name + postfix)
}
}
val greeter = new DefaultGreeter()
greeter.greet("Scala developer") // Hello, Scala developer!
val customGreeter = new CustomizableGreeter("How are you, ", "?")
customGreeter.greet("Scala developer") // How are you, Scala developer?
class DefaultGreeter extends Greeter
class CustomizableGreeter(prefix: String, postfix: String) extends Greeter:
override def greet(name: String): Unit =
println(prefix + name + postfix)
val greeter = DefaultGreeter()
greeter.greet("Scala developer") // Hello, Scala developer!
val customGreeter = CustomizableGreeter("How are you, ", "?")
customGreeter.greet("Scala developer") // How are you, Scala developer?
Здесь DefaultGreeter
наследуется только от одного трейта, но можно наследоваться от нескольких.
Позже мы рассмотрим трейты подробнее.
Главный метод
Главный метод является отправной точкой в программе.
Для Виртуальной Машины Java требуется, чтобы главный метод назывался main
и принимал один аргумент, массив строк.
Используя объект, можно задать главный метод следующим образом:
In Scala 2 you must define a main method manually. Using an object, you can define the main method as follows:
object Main {
def main(args: Array[String]): Unit =
println("Hello, Scala developer!")
}
In Scala 3, with the @main
annotation, a main method is automatically generated from a method as follows:
@main def hello() = println("Hello, Scala developer!")
Дополнительные ресурсы
- Обзор Scala book
Contributors to this page:
Contents
- Введение
- Основы
- Единобразие типов
- Классы
- Значения Параметров По умолчанию
- Именованные Аргументы
- Трейты
- Кортежи
- Композиция классов с трейтами
- Функции Высшего Порядка
- Вложенные Методы
- Множественные списки параметров (Каррирование)
- Классы Образцы
- Сопоставление с примером
- Объекты Одиночки
- Регулярные Выражения
- Объект Экстрактор
- Сложные for-выражения
- Обобщенные Классы
- Вариантность
- Верхнее Ограничение Типа
- Нижнее Ограничение Типа
- Внутренние классы
- Члены Абстрактного Типа
- Составные Типы
- Самоописываемые типы
- Контекстные параметры, также известные, как неявные параметры
- Неявные Преобразования
- Полиморфные методы
- Выведение Типа
- Операторы
- Вызов по имени
- Аннотации
- Пакеты и Импорт
- Объекты Пакета