---
layout: post
title: Основы
next: basics2.textile
---

В этом уроке вы узнаете:
* "Обзор лекций":#overview
* "Выражения":#expressions
* "Переменные":#val
* "Функции":#functions
* "Классы":#class
* "Основы наследования":#extends
* "Трейты":#trait
* "Типы":#types

h2(#overview). Обзор лекций

В первые несколько недель вы узнаете об основах синтаксиса и основных идеях, заложенных в язык Scala. Позже мы начнем раскрывать подробности на примерах.

Некоторые примеры будем писать прямо в интерпретаторе, другие в исходном файле.

Имея под рукой интерпретатор, можно легко исследовать проблемы.

h3. Почему Scala?

* Выразительность
** Функции первого класса
** Замыкания
* Краткость
** Вывод типов
** Буквенный синтаксис для создания функции
* Взаимодействие с Java
** Можно использовать Java библиотеки
** Можно использовать Java инструменты
** Нет потерь производительности

h3. Как работает Scala?

* Компиляция в байт-код Java
* Работает с любой стандартной JVM
** Или даже с некоторыми нестандартными JVM, например Dalvik
** Компилятор Scala написан автором компилятора Java

h3. Что еще нужно знать о Scala

Scala лучше Java в некоторых аспектах. Перед тем как начинать изучать язык Scala, очистите свой разум, из этого выйдет больше толку.

h3. Запускаем интерпретатор

Наберите в консоли <code>sbt console</code>.

<pre>
$ sbt console

[...]

Welcome to Scala version 2.8.0.final (Java HotSpot(TM) 64-Bit Server VM, Java 1.6.0_20).
Type in expressions to have them evaluated.
Type :help for more information.

scala>
</pre>


h2(#expressions). Выражения

<pre>
scala> 1 + 1
res0: Int = 2
</pre>

res0 - автоматически создаваемое имя для переменной, которое интерпретатор дает результату вашего выражения. Переменная имеет тип Int и содержит целочисленное значение 2.

Все (ну, почти) в Scala - выражение.

h2(#val). Константы

Вы можете присвоить собственное имя результату выражения.

<pre>
scala> val two = 1 + 1
two: Int = 2
</pre>

Для переменной с ключевым словом val вы не можете изменить ранее присвоенное значение.

h3. Переменные

Если вам нужно изменить значение константы, вы должны использовать ключевое слово <code>var</code>

<pre>
scala> var name = "steve"
name: java.lang.String = steve

scala> name = "marius"
name: java.lang.String = marius
</pre>

h2(#functions). Функции

Вы можете создать функцию с помощью ключевого слова def.

<pre>
scala> def addOne(m: Int): Int = m + 1
addOne: (m: Int)Int
</pre>

В Scala, вам нужно точно указывать тип, который принимает переменная в параметрах функции. К счастью, интерпретатор возвращает используемый функцией тип обратно.

<pre>
scala> val three = addOne(2)
three: Int = 3
</pre>

Вы можете опускать скобки при использовании функций, если они не имеют аргументов.

<pre>
scala> def three() = 1 + 2
three: ()Int

scala> three()
res2: Int = 3

scala> three
res3: Int = 3
</pre>

h3. Анонимные функции

Вы можете создавать анонимные функции.

<pre>
scala> (x: Int) => x + 1
res2: (Int) => Int = <function1>
</pre>

Эта функция увеличит на 1 значение, которое было передано в анонимную функцию; значение именуется как x.

<pre>
scala> res2(1)
res3: Int = 2
</pre>

Вы можете передавать анонимные функции как параметры или сохранять их в переменных.

<pre>
scala> val addOne = (x: Int) => x + 1
addOne: (Int) => Int = <function1>

scala> addOne(1)
res4: Int = 2
</pre>

Если ваша функция состоит из множества выражений, вы можете использовать фигурные скобки {}, чтобы обезопасить себя.

<pre>
def timesTwo(i: Int): Int = {
  println("hello world")
  i * 2
}
</pre>

Тоже самое верно и для анонимной функции

<pre>
scala> { i: Int =>
  println("hello world")
  i * 2
}
res0: (Int) => Int = <function1>
</pre>

Вы часто будете видеть подобный синтаксис при передачи анонимной функции в качестве параметра.

h3. Частичный вызов функций

Вы можете использовать частичный вызов функций, обозначаемый знаком нижнего подчеркивания(_), этот знак позже будет подменен вызовом функции.

<pre>
scala> def adder(m: Int, n: Int) = m + n
adder: (m: Int,n: Int)Int
</pre>

<pre>
scala> val add2 = adder(2, _:Int)
add2: (Int) => Int = <function1>

scala> add2(3)
res50: Int = 5
</pre>

Вы можете использовать частичный вызов функций с любым аргументом из списка аргументов, а не только с последним из них, как в примере.

h3. Каррирование функций

Иногда требуется передача каких-то аргументов в вашу функцию прямо сейчас, а других через некоторое время.

Ниже пример функции, которая позволяет умножать два числа. В одном месте вызова функции вы решите, какой из аргументов будет множителем, а позднее вызывая функцию, вы сможете установить множимое.

<pre>
scala> def multiply(m: Int)(n: Int): Int = m * n
multiply: (m: Int)(n: Int)Int
</pre>

Вы можете вызвать функцию напрямую с двумя аргументами.

<pre>
scala> multiply(2)(3)
res0: Int = 6
</pre>

Вы можете передать первый аргумент, а второй аргумент объявить как частично вызываемый.

<pre>
scala> val timesTwo = multiply(2) _
timesTwo: (Int) => Int = <function1>

scala> timesTwo(3)
res1: Int = 6
</pre>

Вы можете взять любую функцию с множеством аргументов и произвести ее каррирование. Давайте попробуем использовать функцию, которую рассматривали раньше, например <code>adder</code>

<pre>
scala> (adder _).curried
res1: (Int) => (Int) => Int = <function1>
</pre>

См. подробнее о <a href="https://ru.wikipedia.org/wiki/%D0%9A%D0%B0%D1%80%D1%80%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D0%B5">Каррировании</a>

h3. Использование переменного количества аргументов

Существует специальный синтаксис для методов, которые могут принимать параметры одного и того же типа.

<pre>
def capitalizeAll(args: String*) = {
  args.map { arg =>
    arg.capitalize
  }
}

scala> capitalizeAll("rarity", "applejack")
res2: Seq[String] = ArrayBuffer(Rarity, Applejack)
</pre>

h2(#class). Классы

<pre>
scala> class Calculator {
     |   val brand: String = "HP"
     |   def add(m: Int, n: Int): Int = m + n
     | }

// Здесь мы объявили класс Calculator

scala> val calc = new Calculator
calc: Calculator = Calculator@e75a11

scala> calc.add(1, 2)
res1: Int = 3

scala> calc.brand
res2: String = "HP"
</pre>

В примере объявляется метод и поле с ключевым словом val. Методы - это функции, которые имеют доступ к внутренним сущностям класса.

h3. Конструктор

Конструкторы не являются специальными методами, их код находится в классе за пределами определения метода. Давайте расширим наш пример с калькулятором. Будем принимать аргумент конструктора и использовать его для инициализации внутреннего состояния.

<pre>
class Calculator(brand: String) {
  /**
   * Конструктор.
   */
  val color: String = if (brand == "TI") {
    "blue"
  } else if (brand == "HP") {
    "black"
  } else {
    "white"
  }

  // Метод экземпляра класса.
  def add(m: Int, n: Int): Int = m + n
}
</pre>

Обратите внимание на два различных способа написания комментариев.

h3. Выражения

Наш пример с калькулятором дает хороший пример того, как Scala ориентирован на выражения (expression-oriented). Значение переменной color было присвоено благодаря if/else выражению. Scala сильно ориентирован на выражения: большинство вещей делается с помощью выражений, а не утверждений.

h2(#extends). Наследование

<pre>
class ScientificCalculator(brand: String) extends Calculator(brand) {
  def log(m: Double, base: Double) = math.log(m) / math.log(base)
}
</pre>

*Смотрите также:* В Effective Scala указывается на то, что лучше использовать <a href="https://twitter.github.com/effectivescala/index-ru.html#Типы и обобщенные типы-Псевдонимы типов">Псевдонимы типов</a> вместо <code>extends</code>, особенно если подкласс практически ничем не отличается от суперкласса. В "Туре по языку Scala" вы найдете более подробное описание <a href="https://www.scala-lang.org/node/125">Подклассов</a>.

h3. Перегрузка методов

<pre>
class EvenMoreScientificCalculator(brand: String) extends ScientificCalculator(brand) {
  def log(m: Int): Double = log(m, math.exp(1))
}
</pre>


h2(#trait). Трейты

<code>Трейты</code> - это коллекция полей и методов, которые вы можете расширить или примешать к вашему классу.

<pre>
trait Car {
  val brand: String
}
</pre>

<pre>
class BMW extends Car {
  val brand = "BMW"
}
</pre>

*Смотрите также:* В Effective Scala есть описание <a href="https://twitter.github.com/effectivescala/index-ru.html#Объектно-ориентированное программирование-Трейты(Traits)">Трейтов</a>.

h2(#types). Типы

Ранее вы могли видеть, что мы определили функцию, принимающая тип <code>Int</code>, который является одним из видов Number. Функция может быть объявлена как обобщенная (generic) и после этого может работать с любым типом. Когда объявлена такая функция, вы увидите <pre>параметр-тип</pre> размещенный внутри квадратных скобок:
Вы можете думать о них, как о множестве параметров-типов. Рассмотрим пример трейта Кэш (Cache), который принимает параметры-типы (K, V) для ключей и их значений.

<pre>
trait Cache[K, V] {
  def get(key: K): V
  def put(key: K, value: V)
  def delete(key: K)
}
</pre>

Методы тоже могут иметь параметры-типы

<pre>
def remove[K](key: K)
</pre>
