diff --git a/_data/translations.yml b/_data/translations.yml
index 3641a04203..266b039905 100644
--- a/_data/translations.yml
+++ b/_data/translations.yml
@@ -1,2 +1,2 @@
tour:
- languages: [ba, es, ko, pt-br, pl, zh-cn, th]
+ languages: [ba, es, ko, pt-br, pl, zh-cn, th, ru]
diff --git a/_ru/tour/abstract-type-members.md b/_ru/tour/abstract-type-members.md
new file mode 100644
index 0000000000..cb2a2ecc1e
--- /dev/null
+++ b/_ru/tour/abstract-type-members.md
@@ -0,0 +1,77 @@
+---
+layout: tour
+title: Члены Абстрактного Типа
+
+discourse: true
+
+partof: scala-tour
+num: 23
+language: ru
+next-page: compound-types
+previous-page: inner-classes
+topics: abstract type members
+prerequisite-knowledge: variance, upper-type-bound
+
+---
+
+Абстрактные типы, такие как трейты и абстрактные классы, могут содержать членов абстрактного типа.
+Абстрактный означает, что только конкретный экземпляр определяет, каким именно будет тип.
+Вот пример:
+
+```tut
+trait Buffer {
+ type T
+ val element: T
+}
+```
+Здесь мы определили абстрактный тип `T`, который используется для описания типа члена `element`. Мы можем расширить его в абстрактном классе, добавив верхнюю границу нового типа `U` связанного с `T`, делая описание типа более конкретным.
+
+```tut
+abstract class SeqBuffer extends Buffer {
+ type U
+ type T <: Seq[U]
+ def length = element.length
+}
+```
+Обратите внимание, как мы можем использовать новый абстрактный тип `U` в качестве верхней границы типа. Класс `SeqBuffer` позволяет хранить в буфере только последовательности, указывая, что тип `T` должен быть подтипом `Seq[U]` для нового абстрактного типа `U`.
+
+[Трейты](traits.html) или [классы](classes.html) с членами абстрактного типа часто используются в сочетании с анонимными экземплярами классов. Чтобы проиллюстрировать это рассмотрим программу, которая имеет дело с буфером, который ссылается на список целых чисел:
+
+```tut
+abstract class IntSeqBuffer extends SeqBuffer {
+ type U = Int
+}
+
+
+def newIntSeqBuf(elem1: Int, elem2: Int): IntSeqBuffer =
+ new IntSeqBuffer {
+ type T = List[U]
+ val element = List(elem1, elem2)
+ }
+val buf = newIntSeqBuf(7, 8)
+println("length = " + buf.length)
+println("content = " + buf.element)
+```
+Здесь класс `newIntSeqBuf` создает экземпляры `IntSeqBuffer`, используя анонимную реализацию класса `IntSeqBuffer` (т.е. `new IntSeqBuffer`), устанавливая тип `T` как `List[Int]`.
+
+Мы можем вывести тип класса из типа его членов и наоборот. Приведем версию кода, в которой выводится тип класса из типа его члена:
+
+```tut
+abstract class Buffer[+T] {
+ val element: T
+}
+abstract class SeqBuffer[U, +T <: Seq[U]] extends Buffer[T] {
+ def length = element.length
+}
+
+def newIntSeqBuf(e1: Int, e2: Int): SeqBuffer[Int, Seq[Int]] =
+ new SeqBuffer[Int, List[Int]] {
+ val element = List(e1, e2)
+ }
+
+val buf = newIntSeqBuf(7, 8)
+println("length = " + buf.length)
+println("content = " + buf.element)
+```
+
+Обратите внимание, что здесь необходимо использовать [вариантность в описании типа](variances.html) (`+T <: Seq[U]`) для того, чтобы скрыть конкретный тип реализации списка, возвращаемого из метода `newIntSeqBuf`.
\ No newline at end of file
diff --git a/_ru/tour/annotations.md b/_ru/tour/annotations.md
new file mode 100644
index 0000000000..2016cd1603
--- /dev/null
+++ b/_ru/tour/annotations.md
@@ -0,0 +1,129 @@
+---
+layout: tour
+title: Аннотации
+
+discourse: true
+
+partof: scala-tour
+
+num: 32
+language: ru
+next-page: default-parameter-values
+previous-page: by-name-parameters
+
+---
+
+Аннотации используются для передачи метаданных при объявлении. Например, аннотация `@deprecated` перед объявлением метода, заставит компилятор вывести предупреждение, если этот метод будет использован.
+```
+object DeprecationDemo extends App {
+ @deprecated("deprecation message", "release # which deprecates method")
+ def hello = "hola"
+
+ hello
+}
+```
+Такой код скомпилируется, но компилятор выдаст предупреждение: "there was one deprecation warning".
+
+Аннотация применяется к первому идущему после нее объявлению или определению. Допускается использование сразу нескольких аннотаций следующих друг за другом. Порядок, в котором приводятся аннотации, не имеет значения.
+
+## Аннотации, обеспечивающие корректность работы кода
+Некоторые аннотации приводят к невозможности компиляции, если условие (условия) не выполняется. Например, аннотация `@tailrec` гарантирует, что метод является [хвостовой рекурсией](https://ru.wikipedia.org/wiki/%D0%A5%D0%B2%D0%BE%D1%81%D1%82%D0%BE%D0%B2%D0%B0%D1%8F_%D1%80%D0%B5%D0%BA%D1%83%D1%80%D1%81%D0%B8%D1%8F). Хвостовая рекурсия помогает держать потребление памяти на постоянном уровне. Вот как она используется в методе, который вычисляет факториал:
+
+```tut
+import scala.annotation.tailrec
+
+def factorial(x: Int): Int = {
+
+ @tailrec
+ def factorialHelper(x: Int, accumulator: Int): Int = {
+ if (x == 1) accumulator else factorialHelper(x - 1, accumulator * x)
+ }
+ factorialHelper(x, 1)
+}
+```
+Метод `factorialHelper` имеет аннотацию `@tailrec`, которая гарантирует, что метод действительно является хвостовой рекурсией. Если бы мы изменили реализацию `factorialHelper` так как указано далее, то компиляция бы провалилась:
+```
+import scala.annotation.tailrec
+
+def factorial(x: Int): Int = {
+ @tailrec
+ def factorialHelper(x: Int): Int = {
+ if (x == 1) 1 else x * factorialHelper(x - 1)
+ }
+ factorialHelper(x)
+}
+```
+Мы бы получили сообщение "Recursive call not in tail position"(Рекурсивный вызов не в хвостовой позиции).
+
+
+## Аннотации, влияющие на генерацию кода
+Некоторые аннотации типа `@inline` влияют на сгенерированный код (т.е. в результате сам код вашего jar-файл может отличаться). Такая аннотация означает вставку всего кода в тело метода вместо вызова. Полученный байт-код длиннее, но, надеюсь, работает быстрее. Использование аннотации `@inline` не гарантирует, что метод будет встроен, но заставит компилятор сделать это, если и только если будут соблюдены некоторые разумные требования к размеру сгенерированного кода.
+
+### Java аннотации ###
+Есть некоторые отличий синтаксиса аннотаций, если пишется Scala код, который взаимодействует с Java.
+
+**Примечание:**Убедитесь, что вы используете опцию `-target:jvm-1.8` с аннотациями Java.
+
+Java имеет определяемые пользователем метаданные в виде [аннотаций](https://docs.oracle.com/javase/tutorial/java/annotations/). Ключевой особенностью аннотаций является то, что они задаются в виде пар ключ-значение для инициализации своих элементов. Например, если нам нужна аннотация для отслеживания источника какого-то класса, мы можем определить её как
+
+```
+@interface Source {
+ public String URL();
+ public String mail();
+}
+```
+
+А затем использовать следующим образом
+
+```
+@Source(URL = "http://coders.com/",
+ mail = "support@coders.com")
+public class MyClass extends HisClass ...
+```
+
+Использование аннотации в Scala похоже на вызов конструктора. Для создания экземпляра из Java аннотации необходимо использовать именованные аргументы:
+
+```
+@Source(URL = "http://coders.com/",
+ mail = "support@coders.com")
+class MyScalaClass ...
+```
+
+Этот синтаксис достаточно перегруженный, если аннотация содержит только один элемент (без значения по умолчанию), поэтому, если имя указано как `value`, оно может быть применено в Java с помощью конструктора-подобного синтаксиса:
+
+```
+@interface SourceURL {
+ public String value();
+ public String mail() default "";
+}
+```
+
+А затем можно использовать следующим образом
+
+```
+@SourceURL("http://coders.com/")
+public class MyClass extends HisClass ...
+```
+
+В этом случае Scala предоставляет такую же возможность
+
+```
+@SourceURL("http://coders.com/")
+class MyScalaClass ...
+```
+
+Элемент `mail` был указан со значением по умолчанию, поэтому нам не нужно явно указывать его значение. Мы не можем смешивать эти два стиля в Java:
+
+```
+@SourceURL(value = "http://coders.com/",
+ mail = "support@coders.com")
+public class MyClass extends HisClass ...
+```
+
+Scala обеспечивает большую гибкость в этом отношении
+
+```
+@SourceURL("http://coders.com/",
+ mail = "support@coders.com")
+ class MyScalaClass ...
+```
diff --git a/_ru/tour/automatic-closures.md b/_ru/tour/automatic-closures.md
new file mode 100644
index 0000000000..7de83279d8
--- /dev/null
+++ b/_ru/tour/automatic-closures.md
@@ -0,0 +1,63 @@
+---
+layout: tour
+title: Конструкция Автоматического Замыкания Зависимого Типа
+
+discourse: true
+language: ru
+partof: scala-tour
+num: 14
+---
+
+Scala допускает использование в качестве параметров методов имена беспараметрических функций. При вызове такого метода фактические параметры для беспараметрических функций не вычисляются, а передается функция с нулем аргументов, которая захватывает вычисление соответствующего параметра (так называемый *вызов по имени*).
+
+Следующий код демонстрирует этот механизм:
+
+ object TargetTest1 extends Application {
+ def whileLoop(cond: => Boolean)(body: => Unit): Unit =
+ if (cond) {
+ body
+ whileLoop(cond)(body)
+ }
+ var i = 10
+ whileLoop (i > 0) {
+ println(i)
+ i -= 1
+ }
+ }
+
+Функция whileLoop принимает два параметра `cond` и `body`. При использовании функции значения этих параметров не вычисляются. Но всякий раз, когда параметры используются в теле `whileLoop`, их значение будет вычисляться заново через использование автоматически созданных неявно вызываемых функций. Таким образом, наш метод `whileLoop` реализует Java-подобный цикл while-loop со схемой рекурсивной реализации.
+
+Мы можем комбинировать использование [инфиксных/постфиксных операторов](operators.html) с этим механизмом для создания более сложных выражений (с хорошим синтаксисом).
+
+Вот реализация loop-unless выражения:
+
+ object TargetTest2 extends Application {
+ def loop(body: => Unit): LoopUnlessCond =
+ new LoopUnlessCond(body)
+ protected class LoopUnlessCond(body: => Unit) {
+ def unless(cond: => Boolean) {
+ body
+ if (!cond) unless(cond)
+ }
+ }
+ var i = 10
+ loop {
+ println("i = " + i)
+ i -= 1
+ } unless (i == 0)
+ }
+Функция `loop` принимает только тело цикла и возвращает экземпляр класса `LoopUnlessCond` (который захватывает это тело цикла). Обратите внимание, что тело еще не вычислено. Класс `LoopUnlessCond` имеет метод `unless`, который мы можем использовать как *инфиксный оператор*. Таким образом, мы получаем вполне естественный синтаксис для нашего нового цикла: `loop { < выражение > } unless ( < условие > )`.
+
+
+Ниже приведен вывод выполнения `TargetTest2`:
+
+ i = 10
+ i = 9
+ i = 8
+ i = 7
+ i = 6
+ i = 5
+ i = 4
+ i = 3
+ i = 2
+ i = 1
diff --git a/_ru/tour/basics.md b/_ru/tour/basics.md
new file mode 100644
index 0000000000..bf0257a403
--- /dev/null
+++ b/_ru/tour/basics.md
@@ -0,0 +1,322 @@
+---
+layout: tour
+title: Основы
+
+discourse: true
+
+partof: scala-tour
+
+num: 2
+language: ru
+next-page: unified-types
+previous-page: tour-of-scala
+
+---
+
+На этой странице мы расскажем об основах Scala.
+
+## Попробовать Scala в браузере.
+
+Вы можете запустить Scala в браузере с помощью ScalaFiddle.
+
+1. Зайдите на [https://scalafiddle.io](https://scalafiddle.io).
+2. Вставьте `println("Hello, world!")` в левую панель.
+3. Нажмите кнопку "Run". Вывод отобразится в правой панели.
+
+Это простой способ поэкспериментировать со Scala кодом без всяких настроек.
+
+Большинство примеров кода в этой документации также интегрированы с ScalaFiddle,
+поэтому вы можете поэкспериментировать с ними, просто нажав кнопку Run.
+
+## Выражения
+
+Выражения - это вычислимые утверждения.
+```
+1 + 1
+```
+Вы можете выводить результаты выражений используя `println`.
+
+{% scalafiddle %}
+```tut
+println(1) // 1
+println(1 + 1) // 2
+println("Hello!") // Hello!
+println("Hello," + " world!") // Hello, world!
+```
+{% endscalafiddle %}
+
+### Значения
+
+Результаты выражений можно присваивать именам с помощью ключевого слова `val`.
+
+```tut
+val x = 1 + 1
+println(x) // 2
+```
+
+Названные результаты, такие как `x` в примере, называются значениями.
+Вызов значения не приводит к его повторному вычислению.
+
+Значения не изменяемы и не могут быть переназначены.
+
+```tut:fail
+x = 3 // Не компилируется.
+```
+
+Типы значений могут быть выведены автоматически, но можно и явно указать тип, как показано ниже:
+
+```tut
+val x: Int = 1 + 1
+```
+
+Обратите внимание, что объявление типа `Int` происходит после идентификатора `x`, следующим за `:`.
+
+### Переменные
+
+Переменные похожи на значения константы, за исключением того, что их можно присваивать заново. Вы можете объявить переменную с помощью ключевого слова `var`.
+
+```tut
+var x = 1 + 1
+x = 3 // Компилируется потому что "x" объявлен с ключевым словом "var".
+println(x * x) // 9
+```
+
+Как и в случае со значениями, вы можете явно указать тип, если захотите:
+
+```tut
+var x: Int = 1 + 1
+```
+
+
+## Блоки
+
+Вы можете комбинировать выражения, окружая их `{}`. Мы называем это блоком.
+
+Результат последнего выражения в блоке - будет результатом всего блока в целом.
+
+```tut
+println({
+ val x = 1 + 1
+ x + 1
+}) // 3
+```
+
+## Функции
+
+Функции - это выражения, которые принимают параметры.
+
+Вы можете определить анонимную функцию (т.е. без имени), которая возвращает переданное число прибавив к нему единицу:
+
+```tut
+(x: Int) => x + 1
+```
+
+Слева от `=>` находится список параметров. Справа - выражение, связанное с параметрами.
+
+Вы также можете назвать функции.
+
+{% scalafiddle %}
+```tut
+val addOne = (x: Int) => x + 1
+println(addOne(1)) // 2
+```
+{% endscalafiddle %}
+
+Функции могут принимать множество параметров.
+
+{% scalafiddle %}
+```tut
+val add = (x: Int, y: Int) => x + y
+println(add(1, 2)) // 3
+```
+{% endscalafiddle %}
+
+Или вообще не принимать никаких параметров.
+
+```tut
+val getTheAnswer = () => 42
+println(getTheAnswer()) // 42
+```
+
+## Методы
+
+Методы выглядят и ведут себя очень похоже на функции, но между ними есть несколько принципиальных различий.
+
+Методы задаются ключевым словом `def`. За `def` следует имя, список параметров, возвращаемый тип и тело.
+
+{% scalafiddle %}
+```tut
+def add(x: Int, y: Int): Int = x + y
+println(add(1, 2)) // 3
+```
+{% endscalafiddle %}
+
+Обратите внимание, как объявлен возвращаемый тип сразу _после_ списка параметров и двоеточия `: Int`.
+
+Методы могут принимать несколько списков параметров.
+
+{% scalafiddle %}
+```tut
+def addThenMultiply(x: Int, y: Int)(multiplier: Int): Int = (x + y) * multiplier
+println(addThenMultiply(1, 2)(3)) // 9
+```
+{% endscalafiddle %}
+
+Или вообще ни одного списка параметров.
+
+```tut
+def name: String = System.getProperty("user.name")
+println("Hello, " + name + "!")
+```
+
+Есть некоторые отличия от функций, но пока что их можно рассматривать как нечто похожее.
+
+Методы также могут иметь многострочные выражения.
+```tut
+def getSquareString(input: Double): String = {
+ val square = input * input
+ square.toString
+}
+```
+Последнее выражение в теле становится возвращаемым значением метода. (У Scala есть ключевое слово `return` , но оно практически не используется.)
+
+## Классы
+
+Вы можете объявлять классы используя ключевое слово `class`, за которым следует его имя и параметры конструктора.
+
+```tut
+class Greeter(prefix: String, suffix: String) {
+ def greet(name: String): Unit =
+ println(prefix + name + suffix)
+}
+```
+Возвращаемый тип метода `greet` это `Unit`, используется тогда, когда не имеет смысла что-либо возвращать. Аналогично `void` в Java и C. (Поскольку каждое выражение Scala должно иметь какое-то значение, то при отсутствии возвращающегося значения, возвращается экземпляр типа Unit. Явным образом его можно задать как `()`, он не несет какой-либо информации.)
+
+Вы можете создать экземпляр класса используя ключевое слово `new`.
+
+```tut
+val greeter = new Greeter("Hello, ", "!")
+greeter.greet("Scala developer") // Hello, Scala developer!
+```
+
+Позже мы рассмотрим классы [подробнее](classes.html).
+
+## Классы образцы (Case Class)
+
+В Scala есть специальный тип класса, который называется классом образцом (case class). По умолчанию такие классы неизменны и сравниваются по значению из конструктора. Вы можете объявлять классы образцы с помощью ключевых слов `case class`.
+
+```tut
+case class Point(x: Int, y: Int)
+```
+
+Можно создавать экземпляры класса образца без использования ключевого слова `new`.
+
+```tut
+val point = Point(1, 2)
+val anotherPoint = Point(1, 2)
+val yetAnotherPoint = Point(2, 2)
+```
+
+Они сравниваются по значению.
+
+```tut
+if (point == anotherPoint) {
+ println(point + " and " + anotherPoint + " are the same.")
+} else {
+ println(point + " and " + anotherPoint + " are different.")
+} // Point(1,2) и Point(1,2) одни и те же.
+
+if (point == yetAnotherPoint) {
+ println(point + " and " + yetAnotherPoint + " are the same.")
+} else {
+ println(point + " and " + yetAnotherPoint + " are different.")
+} // Point(1,2) и Point(2,2) разные.
+```
+
+Есть еще много деталей, которые мы бы хотели рассказать про классы образцы, мы уверены, что вы влюбитесь в них! Обязательно рассмотрим их [позже](case-classes.html).
+
+## Объекты
+
+Объекты задаются и существуют в единственным экземпляре. Вы можете думать о них как об одиночках (сингэлтонах) своего собственного класса.
+
+Вы можете задать объекты при помощи ключевого слова `object`.
+
+```tut
+object IdFactory {
+ private var counter = 0
+ def create(): Int = {
+ counter += 1
+ counter
+ }
+}
+```
+
+Вы можете сразу получить доступ к объекту, ссылаясь на его имя.
+
+```tut
+val newId: Int = IdFactory.create()
+println(newId) // 1
+val newerId: Int = IdFactory.create()
+println(newerId) // 2
+```
+
+Позже мы рассмотрим объекты [подробнее](singleton-objects.html).
+
+## Трейты
+
+Трейты - как типы описывают характеристики классов, в нем могут объявляться определенные поля и методы. Трейты можно комбинировать.
+
+Объявить трейт можно с помощью ключевого слова `trait`.
+
+```tut
+trait Greeter {
+ def greet(name: String): Unit
+}
+```
+
+Трейты также могут иметь реализации методов и полей, которые предполагается использовать умолчанию.
+
+{% scalafiddle %}
+```tut
+trait Greeter {
+ def greet(name: String): Unit =
+ println("Hello, " + name + "!")
+}
+```
+
+Вы можете наследовать свойства трейтов используя ключевое словом `extends` и переопределять реализацию с помощью ключевого слова `override`.
+
+```tut
+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?
+```
+{% endscalafiddle %}
+
+Здесь `DefaultGreeter` наследуется только от одного трейта, но можно наследоваться от нескольких.
+
+Позже мы рассмотрим трейты [подробнее](traits.html).
+
+## Главный метод
+
+Главный метод является отправной точкой в программе.
+Для Виртуальной Машины Java требуется, чтобы главный метод назывался `main` и принимал один аргумент, массив строк.
+
+Используя объект, можно задать главный метод следующим образом:
+
+```tut
+object Main {
+ def main(args: Array[String]): Unit =
+ println("Hello, Scala developer!")
+}
+```
diff --git a/_ru/tour/by-name-parameters.md b/_ru/tour/by-name-parameters.md
new file mode 100644
index 0000000000..9cd798b2ee
--- /dev/null
+++ b/_ru/tour/by-name-parameters.md
@@ -0,0 +1,42 @@
+---
+layout: tour
+title: Вызов по имени
+
+discourse: true
+
+partof: scala-tour
+
+num: 31
+language: ru
+next-page: annotations
+previous-page: operators
+
+---
+
+_Вызов параметров по имени_ - это когда значение параметра вычисляется только в момент вызова параметра. Этот способ противоположен _вызову по значению_. Чтоб вызов параметра был по имени, необходимо просто указать `=>` перед его типом.
+```tut
+def calculate(input: => Int) = input * 37
+```
+Преимущество вызова параметров по имени заключается в том, что они не вычисляются если не используются в теле функции. С другой стороны плюсы вызова параметров по значению в том, что они вычисляются только один раз.
+
+Вот пример того, как мы можем реализовать условный цикл:
+
+```tut
+def whileLoop(condition: => Boolean)(body: => Unit): Unit =
+ if (condition) {
+ body
+ whileLoop(condition)(body)
+ }
+
+var i = 2
+
+whileLoop (i > 0) {
+ println(i)
+ i -= 1
+} // выведет 2 1
+```
+Метод `whileLoop` использует несколько списков параметров - условие и тело цикла. Если `condition` является верным, выполняется `body`, а затем выполняется рекурсивный вызов whileLoop. Если `condition` является ложным, то тело никогда не вычисляется, тк у нас стоит `=>` перед типом `body`.
+
+Теперь, когда мы передаем `i > 0` как наше условие `condition` и `println(i); i-= 1` как тело `body`, код ведет себя также как обычный цикл в большинстве языков программирования.
+
+Такая возможность откладывать вычисления параметра до его использования может помочь повысить производительность, отсекая не нужные вычисления при определенных условиях.
diff --git a/_ru/tour/case-classes.md b/_ru/tour/case-classes.md
new file mode 100644
index 0000000000..13c3622587
--- /dev/null
+++ b/_ru/tour/case-classes.md
@@ -0,0 +1,59 @@
+---
+layout: tour
+title: Классы Образцы
+
+discourse: true
+
+partof: scala-tour
+
+num: 11
+language: ru
+next-page: pattern-matching
+previous-page: multiple-parameter-lists
+prerequisite-knowledge: classes, basics, mutability
+
+---
+
+Классы образцы (Case classes) похожи на обычные классы с несколькими ключевыми отличиями, о которых мы поговорим ниже. Классы образцы хороши для моделирования неизменяемых данных. На следующей странице обзора вы увидите, насколько они полезны для участия в [сопоставлении с примером](pattern-matching.html).
+
+## Объявление класса образца
+Минимальный вариант объявления класса образца: указание ключевого слова `case class`, название и список параметров (которые могут быть пустыми). Пример:
+```tut
+case class Book(isbn: String)
+
+val frankenstein = Book("978-0486282114")
+```
+Обратите внимание, что ключевое слово `new` не было использовано для создания экземпляра класса `Book`. Это связано с тем, что классы образцы по умолчанию имеют объект компаньон с методом `apply`, который берет на себя заботу о создании экземпляра класса.
+
+При создании класса образца с параметрами, эти параметры являются публичными и неизменяемыми.
+```
+case class Message(sender: String, recipient: String, body: String)
+val message1 = Message("guillaume@quebec.ca", "jorge@catalonia.es", "Ça va ?")
+
+println(message1.sender) // prints guillaume@quebec.ca
+message1.sender = "travis@washington.us" // эта строка не компилируется
+```
+Вы не можете переназначить `message1.sender`, потому что это `val` (т.е. константа). Возможно использовать `var`s в классах образцах, но это не рекомендуется.
+
+## Сравнение
+Классы образцы сравниваются по структуре, а не по ссылкам:
+```
+case class Message(sender: String, recipient: String, body: String)
+
+val message2 = Message("jorge@catalonia.es", "guillaume@quebec.ca", "Com va?")
+val message3 = Message("jorge@catalonia.es", "guillaume@quebec.ca", "Com va?")
+val messagesAreTheSame = message2 == message3 // true
+```
+Даже если `message2` и `message3` ссылаются на разные объекты, значения каждого из них равна.
+
+## Копирование
+Вы можете создать копию экземпляра класса образца, просто воспользовавшись методом `copy`. При этом по желанию можно изменить аргументы конструктора.
+```
+case class Message(sender: String, recipient: String, body: String)
+val message4 = Message("julien@bretagne.fr", "travis@washington.us", "Me zo o komz gant ma amezeg")
+val message5 = message4.copy(sender = message4.recipient, recipient = "claire@bourgogne.fr")
+message5.sender // travis@washington.us
+message5.recipient // claire@bourgogne.fr
+message5.body // "Me zo o komz gant ma amezeg"
+```
+Получатель `message4` использует в качестве отправителя `message5`, кроме параметра `body` который был скопирован из `message4`.
diff --git a/_ru/tour/classes.md b/_ru/tour/classes.md
new file mode 100644
index 0000000000..0b5a7e0bec
--- /dev/null
+++ b/_ru/tour/classes.md
@@ -0,0 +1,110 @@
+---
+layout: tour
+title: Классы
+
+discourse: true
+
+partof: scala-tour
+
+num: 4
+language: ru
+next-page: traits
+previous-page: unified-types
+topics: classes
+prerequisite-knowledge: no-return-keyword, type-declaration-syntax, string-interpolation, procedures
+
+---
+
+Классы в Scala являются основами для создания объектов. Они могут содержать методы, константы, переменные, типы, объекты, трейты и классы, которые в совокупности называются _членами_. Типы, объекты и трейты будут рассмотрены позже в ходе нашего обзора.
+
+## Объявление класса
+Минимальное объявление класса - это просто ключевое слово `class` и его имя. Имена классов должны быть написаны с заглавной буквы.
+```tut
+class User
+
+val user1 = new User
+```
+Ключевое слово `new` используется для создания экземпляра класса. `User` имеет конструктор по умолчанию, который не принимает аргументов, так как конструктор не был определен. Однако обычно используется и конструктор, и тело класса. Пример объявления класса Point приведен ниже:
+
+```tut
+class Point(var x: Int, var y: Int) {
+
+ def move(dx: Int, dy: Int): Unit = {
+ x = x + dx
+ y = y + dy
+ }
+
+ override def toString: String =
+ s"($x, $y)"
+}
+
+val point1 = new Point(2, 3)
+point1.x // 2
+println(point1) // prints (2, 3)
+```
+
+В этом классе у `Point` есть четыре члена: переменные `x` и `y` и методы `move` и `toString`.
+В отличие от многих других языков, основной конструктор находится в сигнатуре класса `(var x: Int, var y: Int)`. Метод `move` принимает два целочисленных аргумента и возвращает значение Unit `()` - это пустое множество, которое не содержит никакой информации. Примерно соответствует `void` в Java-подобных языках. С другой стороны, `toString` не принимает никаких аргументов, а возвращает значение `String`. Поскольку `toString` переопределяет `toString` из [`AnyRef`](unified-types.html), он помечается ключевым словом `override`.
+
+## Конструкторы
+
+Конструкторы могут иметь необязательные параметры, если указать их значения по умолчанию как в примере:
+
+```tut
+class Point(var x: Int = 0, var y: Int = 0)
+
+val origin = new Point // x и y оба равны 0
+val point1 = new Point(1)
+println(point1.x) // выводит 1
+
+```
+
+В этой версии класса `Point`, `x` и `y` имеют значение по умолчанию `0`, поэтому аргументов не требуется. Однако, поскольку конструктор считывает аргументы слева направо, если вы просто хотите передать значение `y`, то вам нужно будет указать задаваемый параметр.
+```
+class Point(var x: Int = 0, var y: Int = 0)
+val point2 = new Point(y=2)
+println(point2.y) // выводит 2
+```
+
+Что также является хорошей практикой для повышения ясности кода.
+
+## Скрытые члены и синтаксис Геттер/Сеттер (получатель/установщик значений)
+По умолчанию члены класса являются открытыми для внешнего доступа (публичными). Используйте модификатор `private`, чтобы скрыть их от внешнего доступа.
+```tut
+class Point {
+ private var _x = 0
+ private var _y = 0
+ private val bound = 100
+
+ def x = _x
+ def x_= (newValue: Int): Unit = {
+ if (newValue < bound) _x = newValue else printWarning
+ }
+
+ def y = _y
+ def y_= (newValue: Int): Unit = {
+ if (newValue < bound) _y = newValue else printWarning
+ }
+
+ private def printWarning = println("WARNING: Out of bounds")
+}
+
+val point1 = new Point
+point1.x = 99
+point1.y = 101 // выводит предупреждение (printWarning)
+```
+В данной версии класса `Point` данные хранятся в скрытых переменных `_x` и `_y`. Существуют методы `def x` и `def y` для доступа к скрытым данным. Методы `def x_=` и `def y_=` (сеттеры) предназначены для проверки и установки значения `_x` и `_y`. Обратите внимание на специальный синтаксис для сеттеров: метод `_=` применяется к имени геттера.
+
+Первичные параметры конструктора с параметрами `val` и `var` являются общедоступными. Однако, поскольку `val` - это константа, то нельзя писать следующее.
+```
+class Point(val x: Int, val y: Int)
+val point = new Point(1, 2)
+point.x = 3 // <-- не компилируется
+```
+
+Параметры без `val` или `var` являются скрытыми от внешнего доступа и видимы только внутри класса.
+```
+class Point(x: Int, y: Int)
+val point = new Point(1, 2)
+point.x // <-- не компилируется
+```
diff --git a/_ru/tour/compound-types.md b/_ru/tour/compound-types.md
new file mode 100644
index 0000000000..988900cab4
--- /dev/null
+++ b/_ru/tour/compound-types.md
@@ -0,0 +1,54 @@
+---
+layout: tour
+title: Составные Типы
+
+discourse: true
+
+partof: scala-tour
+
+num: 24
+language: ru
+next-page: self-types
+previous-page: abstract-type-members
+
+---
+
+Иногда необходимо выразить, то что тип объекта является подтипом нескольких других типов. В Scala это можно выразить с помощью *составных типов*, которые являются объединением нескольких типов объектов.
+
+Предположим, у нас есть два трейта: `Cloneable` и `Resetable`:
+
+```tut
+trait Cloneable extends java.lang.Cloneable {
+ override def clone(): Cloneable = {
+ super.clone().asInstanceOf[Cloneable]
+ }
+}
+trait Resetable {
+ def reset: Unit
+}
+```
+
+Теперь предположим, что мы хотим написать функцию `cloneAndReset`, которая берет объект, клонирует его и сбрасывает (Reset) состояние исходного объекта:
+
+```
+def cloneAndReset(obj: ?): Cloneable = {
+ val cloned = obj.clone()
+ obj.reset
+ cloned
+}
+```
+
+Возникает вопрос, какой тип параметр `obj` должна принимать наша объединённая функция. Если это `Cloneable`, то объект может использовать метод `clone`, но не `reset`; если это `Resetable` мы можем использовать метод `reset`, но нет операции `clone`. Чтобы избежать приведения типа в такой ситуации, мы можем указать, что тип `obj` является и `Cloneable`, и `Resetable`. Этот совместный тип в Scala записывается как: `Cloneable with Resetable`.
+
+Вот обновленная функция:
+
+```
+def cloneAndReset(obj: Cloneable with Resetable): Cloneable = {
+ //...
+}
+```
+
+Составные типы могут состоять из нескольких типов объектов, и они могут содержать единый доработанный объект, в котором будут доработаны характеристики существующих членов объекта.
+Общая форма записи: `A with B with C ... { доработанный объект }`
+
+Пример использования таких доработок приведен на странице об [объединении классов с примесями](mixin-class-composition.html).
diff --git a/_ru/tour/default-parameter-values.md b/_ru/tour/default-parameter-values.md
new file mode 100644
index 0000000000..7bf61e5430
--- /dev/null
+++ b/_ru/tour/default-parameter-values.md
@@ -0,0 +1,49 @@
+---
+layout: tour
+title: Значения Параметров По умолчанию
+
+discourse: true
+
+partof: scala-tour
+
+num: 33
+language: ru
+next-page: named-arguments
+previous-page: annotations
+prerequisite-knowledge: named-arguments, function syntax
+
+---
+
+Scala предоставляет возможность задавать значения параметров по умолчанию, что позволяет лишний раз не указывать параметры.
+
+```tut
+def log(message: String, level: String = "INFO") = println(s"$level: $message")
+
+log("System starting") // выведет "INFO: System starting"
+log("User not found", "WARNING") // выведет "WARNING: User not found"
+```
+
+У параметра `level` есть значение по умолчанию, поэтому он необязателен. В последней строке аргумент `"WARNING"` переназначает аргумент по умолчанию `"INFO"`. Вместо того чтоб использовать перегруженные методы в Java, вы можете просто указать дополнительные параметры как параметры по умолчанию для достижения того же эффекта. Однако, если при вызове пропущен хотя бы один аргумент, все остальные аргументы должны вызываться с указанием конкретного имени аргумента.
+
+```tut
+class Point(val x: Double = 0, val y: Double = 0)
+
+val point1 = new Point(y = 1)
+```
+Так мы можем указать что `y = 1`.
+
+Обратите внимание, что параметры по умолчанию в Scala, при вызове из Java кода, являются обязательными:
+
+```tut
+// Point.scala
+class Point(val x: Double = 0, val y: Double = 0)
+```
+
+```java
+// Main.java
+public class Main {
+ public static void main(String[] args) {
+ Point point = new Point(1); // не скомпилируется
+ }
+}
+```
diff --git a/_ru/tour/extractor-objects.md b/_ru/tour/extractor-objects.md
new file mode 100644
index 0000000000..d3824e69c3
--- /dev/null
+++ b/_ru/tour/extractor-objects.md
@@ -0,0 +1,65 @@
+---
+layout: tour
+title: Объект Экстрактор
+
+discourse: true
+
+partof: scala-tour
+
+num: 16
+language: ru
+next-page: for-comprehensions
+previous-page: regular-expression-patterns
+
+---
+
+Объект Экстрактор (объект распаковщик или extractor object) - это объект с методом `unapply`. В то время как метод `apply` обычно действует как конструктор, который принимает аргументы и создает объект, метод `unapply` действует обратным образом, он принимает объект и пытается извлечь и вернуть аргументы из которых он (возможно) был создан. Чаще всего этот метод используется в функциях сопоставления с примером и в частично определенных функциях.
+
+```tut
+import scala.util.Random
+
+object CustomerID {
+
+ def apply(name: String) = s"$name--${Random.nextLong}"
+
+ def unapply(customerID: String): Option[String] = {
+ val stringArray: Array[String] = customerID.split("--")
+ if (stringArray.tail.nonEmpty) Some(stringArray.head) else None
+ }
+}
+
+val customer1ID = CustomerID("Sukyoung") // Sukyoung--23098234908
+customer1ID match {
+ case CustomerID(name) => println(name) // выведет Sukyoung
+ case _ => println("Could not extract a CustomerID")
+}
+```
+Метод `apply` создает `CustomerID` из строки `name`. `unapply` делает обратное, чтобы вернуть `name` обратно. Когда мы вызываем `CustomerID("Sukyoung")`, это сокращенный синтаксис вызова `CustomerID.apply("Sukyoung")`. Когда мы вызываем `case CustomerID(name) => println(name)`, мы на самом деле вызываем метод `unapply`.
+
+При объявлении нового значения можно использовать пример, в котором значение для инициализации переменной получается через извлечение, используя метод `unapply`.
+
+```tut
+val customer2ID = CustomerID("Nico")
+val CustomerID(name) = customer2ID
+println(name) // выведет Nico
+```
+
+Что эквивалентно `val name = CustomerID.unapply(customer2ID).get`.
+
+```tut
+val CustomerID(name2) = "--asdfasdfasdf"
+```
+
+Если совпадений нет, то бросается `scala.MatchError`:
+
+```tut:fail
+val CustomerID(name3) = "-asdfasdfasdf"
+```
+
+Возвращаемый тип `unapply` выбирается следующим образом:
+
+* Если это всего лишь тест, возвращается `Boolean`. Например `case even()`.
+* Если в результате найдено одно значение типа `T`, то возвращается `Option[T]`.
+* Если вы хотите получить несколько значений `T1,..., Tn`, то ответ необходимо группировать в дополнительный кортеж `Option[(T1,..., Tn)]`.
+
+Иногда количество извлекаемых значений не является фиксированным. Если в зависимости от входа мы хотим вернуть произвольное количество значений, то для этого случая мы можем определить экстрактор методом `unapplySeq`, который возвращает `Option[Seq[T]]`. Характерным примером такого подхода является разложение `List` с помощью `case List(x, y, z) =>` и разложение `String` с помощью регулярного выражения `Regex`, такого как `case r(name, remainingFields @ _*) =>`.
diff --git a/_ru/tour/for-comprehensions.md b/_ru/tour/for-comprehensions.md
new file mode 100644
index 0000000000..5c79ca062c
--- /dev/null
+++ b/_ru/tour/for-comprehensions.md
@@ -0,0 +1,66 @@
+---
+layout: tour
+title: Сложные for-выражения
+
+discourse: true
+
+partof: scala-tour
+
+num: 17
+language: ru
+next-page: generic-classes
+previous-page: extractor-objects
+
+---
+
+Scala предлагает простую запись для выражения *последовательных преобразований*. Эти преобразования можно упростить используя специальный синтаксис `for выражения` (for comprehension), который записывается как `for (enumerators) yield e`, где `enumerators` относятся к списку перечислителей, разделенных точкой с запятой. Где отдельный такой "перечислитель" (*enumerator*) является либо генератором, который вводит новые переменные, либо фильтром. For-выражение вычисляет тело `e` (которое связанно с тем что генерирует *enumerator*) и возвращает последовательность вычислений.
+
+Вот пример:
+
+```tut
+case class User(name: String, age: Int)
+
+val userBase = List(User("Travis", 28),
+ User("Kelly", 33),
+ User("Jennifer", 44),
+ User("Dennis", 23))
+
+val twentySomethings = for (user <- userBase if (user.age >=20 && user.age < 30))
+ yield user.name // т. е. добавить результат к списку
+
+twentySomethings.foreach(name => println(name)) // выводит "Travis Dennis"
+```
+ `for`-выражение, используется с оператором `yield`, на самом деле создает `List`. Потому что мы указали `yield user.name` (то есть вывести имя пользователя), получаем `List[String]`. `user <- userBase` и есть наш генератор, а `if (user.age >=20 && user.age < 30)` - это фильтр который отфильтровывает пользователей, не достигших 20-летнего возраста.
+
+Ниже приведен более сложный пример использования двух генераторов. Он вычисляет все пары чисел между `0` и `n-1`, сумма которых равна заданному значению `v`:
+
+```tut
+def foo(n: Int, v: Int) =
+ for (i <- 0 until n;
+ j <- i until n if i + j == v)
+ yield (i, j)
+
+foo(10, 10) foreach {
+ case (i, j) =>
+ println(s"($i, $j) ") // выводит (1, 9) (2, 8) (3, 7) (4, 6) (5, 5)
+}
+
+```
+Здесь `n == 10` и `v == 10`. На первой итерации `i == 0` и `j == 0` так `i + j != v` и поэтому ничего не выдается. `j` увеличивается еще в 9 раз, прежде чем `i` увеличивается до `1`. Без фильтра `if` будет просто напечатано следующее:
+```
+
+(0, 0) (0, 1) (0, 2) (0, 3) (0, 4) (0, 5) (0, 6) (0, 7) (0, 8) (0, 9) (1, 1) ...
+```
+
+Обратите внимание, что for-выражение не ограничивается только работой со списками. Каждый тип данных, поддерживающий операции `withFilter`, `map`, and `flatMap` (с соответствующими типами), может быть использован в for-выражении.
+
+Вы можете обойтись без `yield` в for-выражении. В таком случае, результатом будет `Unit`. Это может быть полезным для выполнения кода основанного на побочных эффектах. Вот программа, эквивалентная предыдущей, но без использования `yield`:
+
+```tut
+def foo(n: Int, v: Int) =
+ for (i <- 0 until n;
+ j <- i until n if i + j == v)
+ println(s"($i, $j)")
+
+foo(10, 10)
+```
diff --git a/_ru/tour/generic-classes.md b/_ru/tour/generic-classes.md
new file mode 100644
index 0000000000..30587567ca
--- /dev/null
+++ b/_ru/tour/generic-classes.md
@@ -0,0 +1,59 @@
+---
+layout: tour
+title: Обобщенные Классы
+
+discourse: true
+
+partof: scala-tour
+
+num: 18
+language: ru
+next-page: variances
+previous-page: for-comprehensions
+assumed-knowledge: classes unified-types
+
+---
+Обобщенные классы (Generic classes) - это классы, обладающие параметрическим полиморфизмом (т. е. классы, которые изменяют свое поведение в зависимости от приписываемого им типа. Этот тип указывается в квадратных скобках `[]` сразу после имени класса). Они особенно полезны для создания коллекций.
+
+## Объявление обобщенного класса
+Для объявления обобщенного класса необходимо после имени добавить тип в квадратных скобках `[]` как еще один параметр класса. По соглашению обычно используют заглавные буквы `A`, хотя можно использовать любые имена.
+```tut
+class Stack[A] {
+ private var elements: List[A] = Nil
+ def push(x: A) { elements = x :: elements }
+ def peek: A = elements.head
+ def pop(): A = {
+ val currentTop = peek
+ elements = elements.tail
+ currentTop
+ }
+}
+```
+Данная реализация класса `Stack` принимает в качестве параметра любой тип `A`. Это означает что список, `var elements: List[A] = Nil`, может хранить только элементы типа `A`. Процедура `def push` принимает только объекты типа `A` (примечание: `elements = x :: elements` переназначает `elements` в новый список, созданный путем добавления `x`а к текущим `elements`).
+
+## Использование
+
+Чтобы использовать обобщенный класс, поместите конкретный тип в квадратные скобки вместо `A`.
+```
+val stack = new Stack[Int]
+stack.push(1)
+stack.push(2)
+println(stack.pop) // выведет 2
+println(stack.pop) // выведет 1
+```
+Экземпляр `stack` может принимать только Intы. Однако, если тип имеет подтипы, то они также могут быть приняты:
+```
+class Fruit
+class Apple extends Fruit
+class Banana extends Fruit
+
+val stack = new Stack[Fruit]
+val apple = new Apple
+val banana = new Banana
+
+stack.push(apple)
+stack.push(banana)
+```
+Классы `Apple` и `Banana` наследуются от `Fruit` так, что мы можем засунуть экземпляры `Apple` и `Banana` в пачку `Fruit`.
+
+_Примечание: подтипы обобщенных типов - *инвариантны*. Это означает, что если у нас есть стэк символов типа `Stack[Char]`, то он не может быть использован как стек интов типа `Stack[Int]`. Это нежелательное поведение, потому как позволило бы нам добавлять в стек символов целые числа. В заключение, `Stack[A]` является подтипом `Stack[B]` тогда и только тогда, когда `B = A`. Поскольку это может быть довольно строгим ограничением, Scala предлагает [механизм вариативного описания параметров типа](variances.html) для контроля за поведением подтипов._
diff --git a/_ru/tour/higher-order-functions.md b/_ru/tour/higher-order-functions.md
new file mode 100644
index 0000000000..6df55532e9
--- /dev/null
+++ b/_ru/tour/higher-order-functions.md
@@ -0,0 +1,109 @@
+---
+layout: tour
+title: Функции Высшего Порядка
+
+discourse: true
+
+partof: scala-tour
+
+num: 8
+language: ru
+next-page: nested-functions
+previous-page: mixin-class-composition
+
+---
+
+Функции высшего порядка могут принимать другие функции в качестве параметров или возвращать функцию в качестве результата
+Такое возможно поскольку функции являются объектами первого класса в Scala.
+На текущем этапе терминология может казаться немного запутанной, мы используем следующую фразу "функция высшего порядка" как для методов, так и для функций, которые могут принимать другие функции в качестве параметров, или возвращать функции в качестве результата.
+
+Одним из наиболее распространенных примеров функции высшего порядка
+является функция `map`, которая доступна в коллекциях Scala.
+```tut
+val salaries = Seq(20000, 70000, 40000)
+val doubleSalary = (x: Int) => x * 2
+val newSalaries = salaries.map(doubleSalary) // List(40000, 140000, 80000)
+```
+`doubleSalary` - это функция, которая принимает один Int `x` и возвращает `x * 2`. В общем случае, кортеж (список имен в скобках) слева от стрелки `=>` - это список параметров, а значение выражения следует справа. Это же значение возвращается в качестве результата. В строке 3 к каждому элементу списка зарплат (salaries) применяется функция `doubleSalary`.
+
+Чтобы сократить код, мы можем сделать функцию анонимной и передать ее напрямую в качестве аргумента в map:
+```
+val salaries = Seq(20000, 70000, 40000)
+val newSalaries = salaries.map(x => x * 2) // List(40000, 140000, 80000)
+```
+Обратите внимание, что в приведенном выше примере `x`не объявлен как `Int`. Это потому, что компилятор может вывести тип, основываясь на типе который ожидает функция map. Еще более элегантным способом написания этого же кода было бы таким:
+
+```tut
+val salaries = Seq(20000, 70000, 40000)
+val newSalaries = salaries.map(_ * 2)
+```
+Поскольку компилятор Scala уже знает тип параметров (Int), вам нужно только указать правую часть функции. Единственное условие заключается в том, что вместо имени параметра необходимо использовать `_` (в предыдущем примере это было `x`).
+
+## Преобразование методов в функции
+Также возможно передавать методы в качестве аргументов функциям более высокого порядка, поскольку компилятор Scala может преобразовать метод в функцию.
+```
+case class WeeklyWeatherForecast(temperatures: Seq[Double]) {
+
+ private def convertCtoF(temp: Double) = temp * 1.8 + 32
+
+ def forecastInFahrenheit: Seq[Double] = temperatures.map(convertCtoF) // <-- передается метод convertCtoF
+}
+```
+Здесь метод `convertCtoF` передается в `forecastInFahrenheit`. Это возможно, потому что компилятор преобразовывает `convertCtoF` в функцию `x => ConvertCtoF(x)` (примечание: `x` будет сгенерированным именем, которое гарантированно будет уникальным в рамках своей области видимости).
+
+## Функции, которые принимают функции
+Одной из причин использования функций высшего порядка является сокращение избыточного кода. Допустим, вам нужны какие-то методы, которые могли бы повышать чью-то зарплату по разным условиям. Без создания функции высшего порядка это могло бы выглядеть примерно так:
+
+```tut
+object SalaryRaiser {
+
+ def smallPromotion(salaries: List[Double]): List[Double] =
+ salaries.map(salary => salary * 1.1)
+
+ def greatPromotion(salaries: List[Double]): List[Double] =
+ salaries.map(salary => salary * math.log(salary))
+
+ def hugePromotion(salaries: List[Double]): List[Double] =
+ salaries.map(salary => salary * salary)
+}
+```
+
+Обратите внимание, что каждый из этих трех методов отличается только коэффициентом умножения. Для упрощения можно перенести повторяющийся код в функцию высшего порядка:
+
+```tut
+object SalaryRaiser {
+
+ private def promotion(salaries: List[Double], promotionFunction: Double => Double): List[Double] =
+ salaries.map(promotionFunction)
+
+ def smallPromotion(salaries: List[Double]): List[Double] =
+ promotion(salaries, salary => salary * 1.1)
+
+ def bigPromotion(salaries: List[Double]): List[Double] =
+ promotion(salaries, salary => salary * math.log(salary))
+
+ def hugePromotion(salaries: List[Double]): List[Double] =
+ promotion(salaries, salary => salary * salary)
+}
+```
+
+Новый метод, `promotion`, берет зарплату и функцию типа `Double => Double` (т.е. функция, которая берет Double и возвращает Double) и возвращает их произведение.
+
+## Функции, возвращающие функции
+
+Есть определенные случаи, когда вы хотите сгенерировать функцию. Вот пример метода, который возвращает функцию.
+
+```tut
+def urlBuilder(ssl: Boolean, domainName: String): (String, String) => String = {
+ val schema = if (ssl) "https://" else "http://"
+ (endpoint: String, query: String) => s"$schema$domainName/$endpoint?$query"
+}
+
+val domainName = "www.example.com"
+def getURL = urlBuilder(ssl=true, domainName)
+val endpoint = "users"
+val query = "id=1"
+val url = getURL(endpoint, query) // "https://www.example.com/users?id=1": String
+```
+
+Обратите внимание, что возвращаемый тип urlBuilder`(String, String) => String`. Это означает, что возвращаемая анонимная функция принимает две строки и возвращает строку. В нашем случае возвращаемая анонимная функция `(endpoint: String, query: String) => s"https://www.example.com/$endpoint?$query"`.
\ No newline at end of file
diff --git a/_ru/tour/implicit-conversions.md b/_ru/tour/implicit-conversions.md
new file mode 100644
index 0000000000..1040f47f9b
--- /dev/null
+++ b/_ru/tour/implicit-conversions.md
@@ -0,0 +1,63 @@
+---
+layout: tour
+title: Неявные Преобразования
+
+discourse: true
+
+partof: scala-tour
+
+num: 27
+language: ru
+next-page: polymorphic-methods
+previous-page: implicit-parameters
+
+---
+
+Неявные преобразование типа `S` к типу `T` задается неявным значением функционального типа `S =>T`, или неявным методом, который способен преобразовывать к значению требуемого типа.
+
+Неявное преобразование применяются в двух случаях:
+
+* Если выражение `e` типа `S` не подходит под ожидаемый тип выражения `T`.
+* Если мы выбирая член `e.m`, где `e` является представителем типа `S`, при этом выбранное имя `m` не найдено среди доступных селекторов принадлежащих типу `S`.
+
+В первом случае выполняется поиск приведения `c`, которое можно применить к `e` чтоб тип результата стал соответствовать ожидаемому `T`.
+Во втором случае выполняется поиск преобразования `c`, которое применимо к `e` и результат которого бы содержал член с именем `m`.
+
+Если неявный метод `List[A] => Ordered[List[A]]` находится в области видимости, также как и неявный метод `Int => Ordered[Int]`, то следующая операция с двумя списками типа `List[Int]` является допустимой:
+
+```
+List(1, 2, 3) <= List(4, 5)
+```
+
+Неявный метод `Int => Ordered[Int]` предоставляется автоматически через `scala.Predef.intWrapper`. Ниже приведен пример объявления неявного метода `List[A] => Ordered[List[A]]`.
+
+```tut
+import scala.language.implicitConversions
+
+implicit def list2ordered[A](x: List[A])
+ (implicit elem2ordered: A => Ordered[A]): Ordered[List[A]] =
+ new Ordered[List[A]] {
+ //заменить на более полезную реализацию
+ def compare(that: List[A]): Int = 1
+ }
+```
+
+Неявно импортируемый объект `scala.Predef` объявляет ряд псевдонимов для часто используемым типов (например, `scala.collection.immutable.Map` использует псевдоним `Map`) и методов (например, `assert`), а также делает доступным целую серию неявных преобразований.
+
+Например, при вызове Java метода, который ожидает `java.lang.Integer`, вместо него вы можете свободно использовать `scala.Int`. Потому что Predef включает в себя следующие неявные преобразования:
+
+```tut
+import scala.language.implicitConversions
+
+implicit def int2Integer(x: Int) =
+ java.lang.Integer.valueOf(x)
+```
+
+Компилятор предупреждает при компиляции об обнаружении неявных преобразований, тк неявные преобразования могут иметь разные подводные камни (особенно если использовать их без разбора).
+
+Чтоб отключить предупреждения выполните одно из следующих действий:
+
+* Импортируйте `scala.language.implicitConversions` в области видимости, где объявлены неявные преобразования.
+* Вызывайте компилятор с ключом `-language:implicitConversions`.
+
+В таком случае при преобразовании компилятором не будет выдаваться никаких предупреждений.
diff --git a/_ru/tour/implicit-parameters.md b/_ru/tour/implicit-parameters.md
new file mode 100644
index 0000000000..e9f7756e15
--- /dev/null
+++ b/_ru/tour/implicit-parameters.md
@@ -0,0 +1,73 @@
+---
+layout: tour
+title: Неявные Параметры
+
+discourse: true
+
+partof: scala-tour
+
+num: 26
+language: ru
+next-page: implicit-conversions
+previous-page: self-types
+
+---
+
+Метод может иметь список _неявных_ параметров, помеченный ключевым словом _implicit_ в начале списка параметров. Если параметры в этом списке не передаются как обычно, то Scala будет искать, где можно получить неявное значение требуемого типа, и если найдет, то передаст его автоматически.
+
+Места, где Scala будет искать эти параметры, делятся на две категории:
+
+* Скала сначала будет искать неявные параметры, доступ к которым можно получить напрямую (без префикса) в месте вызова метода в котором запрошены неявные параметры.
+* Затем он ищет членов, помеченных как implicit во всех объектах компаньонах, связанных с типом неявного параметра.
+
+Более подробное руководство, о том где scala ищет неявные значения можно найти в [FAQ](//docs.scala-lang.org/tutorials/FAQ/finding-implicits.html)
+
+В следующем примере мы определяем метод `sum`, который вычисляет сумму элементов списка, используя операции `add` и `unit` моноида. Обратите внимание, что неявные значения не могут находится выше уровнем.
+
+```tut
+abstract class Monoid[A] {
+ def add(x: A, y: A): A
+ def unit: A
+}
+
+object ImplicitTest {
+ implicit val stringMonoid: Monoid[String] = new Monoid[String] {
+ def add(x: String, y: String): String = x concat y
+ def unit: String = ""
+ }
+
+ implicit val intMonoid: Monoid[Int] = new Monoid[Int] {
+ def add(x: Int, y: Int): Int = x + y
+ def unit: Int = 0
+ }
+
+ def sum[A](xs: List[A])(implicit m: Monoid[A]): A =
+ if (xs.isEmpty) m.unit
+ else m.add(xs.head, sum(xs.tail))
+
+ def main(args: Array[String]): Unit = {
+ println(sum(List(1, 2, 3))) // использует intMonoid неявно
+ println(sum(List("a", "b", "c"))) // использует stringMonoid неявно
+ }
+}
+```
+
+`Monoid` определяет здесь операцию под названием `add`, которая сочетает два элемента типа `A` и возвращает сумму типа `A`, операция `unit` позволяет вернуть отдельный (специфичный) элемент типа `A`.
+
+Чтобы показать, как работают неявные параметры, сначала определим моноиды `stringMonoid` и `intMonoid` для строк и целых чисел, соответственно. Ключевое слово `implicit` указывает на то, что этот объект может быть использован неявно.
+
+Метод `sum` принимает `List[A]` и возвращает `A`, который берет начальное `A` из `unit` и объединяет каждое следующее `A` в списке используя `add` метод. Указание параметра `m` в качестве неявного параметра подразумевает, что `xs` параметр будет обеспечен тогда, когда при вызове параметра метода Scala сможет найти неявный `Monoid[A]` чтоб его передать в качестве параметра `m`.
+
+В нашем `main` методе мы вызываем `sum` дважды и предоставляем только `xs` параметр. Теперь Scala будет искать неявное значение в указанных ранее областях видимости. Первый вызов `sum` проходит с использованием `List[Int]` в качестве `xs`, это означает, что элемент `A` имеет тип `Int`. Неявный список параметров с `m` опущен, поэтому Scala будет искать неявное значение типа `Monoid[Int]`. Первое правило поиска гласит
+
+> Скала сначала будет искать неявные параметры, доступ к которым можно получить напрямую (без префикса) в месте вызова метода в котором запрошены неявные параметры.
+
+`intMonoid` - это задание неявного значения, доступ к которому можно получить непосредственно в `main`. Оно имеет подходящий тип, поэтому передается методу `sum` автоматически.
+
+Второй вызов `sum` проходит используя `List[String]`, что означает, что `A` - это `String`. Неявный поиск будет идти так же, как и в случае с `Int`, но на этот раз будет найден `stringMonoid`, и передан автоматически в качестве `m`.
+
+Программа выведет на экран
+```
+6
+abc
+```
diff --git a/_ru/tour/inner-classes.md b/_ru/tour/inner-classes.md
new file mode 100644
index 0000000000..64fca34b24
--- /dev/null
+++ b/_ru/tour/inner-classes.md
@@ -0,0 +1,81 @@
+---
+layout: tour
+title: Внутренние классы
+
+discourse: true
+
+partof: scala-tour
+
+num: 22
+language: ru
+next-page: abstract-type-members
+previous-page: lower-type-bounds
+
+---
+
+В Scala классам можно иметь в качестве членов другие классы. В отличие от Java-подобных языков, где такие внутренние классы являются членами окружающего класса, в Scala такие внутренние классы привязаны к содержащему его объекту. Предположим, мы хотим, чтобы компилятор не позволял нам на этапе компиляции смешивать узлы этого графа. Для решения этой задачи нам подойдут типы, зависящие от своего расположения.
+
+Чтобы проиллюстрировать суть подхода, мы быстро набросаем реализацию такого графа:
+
+```tut
+class Graph {
+ class Node {
+ var connectedNodes: List[Node] = Nil
+ def connectTo(node: Node) {
+ if (connectedNodes.find(node.equals).isEmpty) {
+ connectedNodes = node :: connectedNodes
+ }
+ }
+ }
+ var nodes: List[Node] = Nil
+ def newNode: Node = {
+ val res = new Node
+ nodes = res :: nodes
+ res
+ }
+}
+```
+Данная программа представляет собой граф в составленного из списка узлов (`List[Node]`). Каждый узел имеет список других узлов, с которым он связан (`connectedNodes`). Класс `Node` является _зависимым от месторасположения типом_, поскольку он вложен в `Class Graph`. Поэтому все узлы в `connectedNodes` должны быть созданы с использованием `newNode` из одного и того же экземпляра `Graph`.
+
+```tut
+val graph1: Graph = new Graph
+val node1: graph1.Node = graph1.newNode
+val node2: graph1.Node = graph1.newNode
+val node3: graph1.Node = graph1.newNode
+node1.connectTo(node2)
+node3.connectTo(node1)
+```
+Мы явно объявили тип `node1`, `node2` и `node3` как `graph1.Node` для ясности, хотя компилятор мог определить это самостоятельно. Это потому, что когда мы вызываем `graph1.newNode`, вызывающий `new Node`, метод использует экземпляр `Node`, специфичный экземпляру `graph1`.
+
+Если у нас есть два графа, то система типов Scala не позволит смешивать узлы, определенные в рамках одного графа, с узлами другого, так как узлы другого графа имеют другой тип.
+Вот некорректная программа:
+
+```
+val graph1: Graph = new Graph
+val node1: graph1.Node = graph1.newNode
+val node2: graph1.Node = graph1.newNode
+node1.connectTo(node2) // работает
+val graph2: Graph = new Graph
+val node3: graph2.Node = graph2.newNode
+node1.connectTo(node3) // не работает!
+```
+Тип `graph1.Node` отличается от типа `graph2.Node`. В Java последняя строка в предыдущем примере программы была бы правильной. Для узлов обоих графов Java будет присваивать один и тот же тип `Graph.Node`, т.е. `Node` имеет префикс класса `Graph`. В Скале такой тип также может быть выражен, он записывается `Graph#Node`. Если мы хотим иметь возможность соединять узлы разных графов, то вам нужно изменить описание первоначальной реализации графов следующим образом:
+
+```tut
+class Graph {
+ class Node {
+ var connectedNodes: List[Graph#Node] = Nil
+ def connectTo(node: Graph#Node) {
+ if (connectedNodes.find(node.equals).isEmpty) {
+ connectedNodes = node :: connectedNodes
+ }
+ }
+ }
+ var nodes: List[Node] = Nil
+ def newNode: Node = {
+ val res = new Node
+ nodes = res :: nodes
+ res
+ }
+}
+```
diff --git a/_ru/tour/lower-type-bounds.md b/_ru/tour/lower-type-bounds.md
new file mode 100644
index 0000000000..fe42c61630
--- /dev/null
+++ b/_ru/tour/lower-type-bounds.md
@@ -0,0 +1,70 @@
+---
+layout: tour
+title: Нижнее Ограничение Типа
+
+discourse: true
+
+partof: scala-tour
+
+num: 21
+language: ru
+next-page: inner-classes
+previous-page: upper-type-bounds
+prerequisite-knowledge: upper-type-bounds, generics, variance
+
+---
+
+В то время как [верхнее ограничение типа](upper-type-bounds.html) ограничивает тип до подтипа стороннего типа, *нижнее ограничение типа* объявляют тип супертипом стороннего типа. Термин `B >: A` выражает, то что параметр типа `B` или абстрактный тип `B` относится к супертипу типа `A`. В большинстве случаев `A` будет задавать тип класса, а `B` задавать тип метода.
+
+Вот пример, где это полезно:
+
+```tut:fail
+trait Node[+B] {
+ def prepend(elem: B): Node[B]
+}
+
+case class ListNode[+B](h: B, t: Node[B]) extends Node[B] {
+ def prepend(elem: B): ListNode[B] = ListNode(elem, this)
+ def head: B = h
+ def tail: Node[B] = t
+}
+
+case class Nil[+B]() extends Node[B] {
+ def prepend(elem: B): ListNode[B] = ListNode(elem, this)
+}
+```
+
+В данной программе реализован связанный список. `Nil` представляет пустой список. Класс `ListNode` - это узел, который содержит элемент типа `B` (`head`) и ссылку на остальную часть списка (`tail`). Класс `Node` и его подтипы ковариантны, потому что у нас указанно `+B`.
+
+Однако эта программа _не компилируется_, потому что параметр `elem` в `prepend` имеет тип `B`, который мы объявили *ко*вариантным. Так это не работает, потому что функции *контр*вариантны в типах своих параметров и *ко*вариантны в типах своих результатов.
+
+Чтобы исправить это, необходимо перевернуть вариантность типа параметра `elem` в `prepend`. Для этого мы вводим новый тип для параметра `U`, у которого тип `B` указан в качестве нижней границы типа.
+
+```tut
+trait Node[+B] {
+ def prepend[U >: B](elem: U): Node[U]
+}
+
+case class ListNode[+B](h: B, t: Node[B]) extends Node[B] {
+ def prepend[U >: B](elem: U): ListNode[U] = ListNode(elem, this)
+ def head: B = h
+ def tail: Node[B] = t
+}
+
+case class Nil[+B]() extends Node[B] {
+ def prepend[U >: B](elem: U): ListNode[U] = ListNode(elem, this)
+}
+```
+
+Теперь мы можем сделать следующее:
+```tut
+trait Bird
+case class AfricanSwallow() extends Bird
+case class EuropeanSwallow() extends Bird
+
+
+val africanSwallowList= ListNode[AfricanSwallow](AfricanSwallow(), Nil())
+val birdList: Node[Bird] = africanSwallowList
+birdList.prepend(new EuropeanSwallow)
+```
+`Node[Bird]` может быть присвоен `africanSwallowList` , но затем может добавлять и `EuropeanSwallow`.
diff --git a/_ru/tour/mixin-class-composition.md b/_ru/tour/mixin-class-composition.md
new file mode 100644
index 0000000000..4c528ca3c9
--- /dev/null
+++ b/_ru/tour/mixin-class-composition.md
@@ -0,0 +1,83 @@
+---
+layout: tour
+title: Композиция классов с примесями
+
+discourse: true
+
+partof: scala-tour
+
+num: 7
+language: ru
+next-page: higher-order-functions
+previous-page: tuples
+prerequisite-knowledge: inheritance, traits, abstract-classes, unified-types
+
+---
+Примеси (Mixin) - это трейты, которые используются для создания класса.
+
+```tut
+abstract class A {
+ val message: String
+}
+class B extends A {
+ val message = "I'm an instance of class B"
+}
+trait C extends A {
+ def loudMessage = message.toUpperCase()
+}
+class D extends B with C
+
+val d = new D
+println(d.message) // I'm an instance of class B
+println(d.loudMessage) // I'M AN INSTANCE OF CLASS B
+```
+У класса `D` есть суперкласс `B` и примесь `C`. Классы могут иметь только один суперкласс, но много примесей (используя ключевыое слово `extends` и `with` соответственно). Примеси и суперкласс могут иметь один и тот же супертип.
+
+Теперь давайте рассмотрим более интересный пример, начиная с абстрактного класса:
+
+```tut
+abstract class AbsIterator {
+ type T
+ def hasNext: Boolean
+ def next(): T
+}
+```
+Класс имеет абстрактный тип `T` и методы стандартного итератора.
+
+Далее создаем конкретную реализацию класса (все абстрактные члены `T`, `hasNext`, и `next` должны быть реализованы):
+
+```tut
+class StringIterator(s: String) extends AbsIterator {
+ type T = Char
+ private var i = 0
+ def hasNext = i < s.length
+ def next() = {
+ val ch = s charAt i
+ i += 1
+ ch
+ }
+}
+```
+`StringIterator` принимает `String` и может быть использован для обхода по строке (например, чтоб проверить содержит ли строка определенный символ).
+
+Теперь давайте создадим трейт который тоже наследуется от `AbsIterator`.
+
+```tut
+trait RichIterator extends AbsIterator {
+ def foreach(f: T => Unit): Unit = while (hasNext) f(next())
+}
+```
+У этого трейта реализован метод `foreach` который постоянно вызывает переданную ему функцию `f: T => Unit` на каждом новом элементе (`next()`) до тех пор пока в итераторе содержатся элементы (`while (hasNext)`). Поскольку `RichIterator` это трейт, ему не нужно реализовывать членов абстрактного класса `AbsIterator`.
+
+Мы бы хотели объединить функциональность `StringIterator` и `RichIterator` в один класс.
+
+```tut
+object StringIteratorTest extends App {
+ class RichStringIter extends StringIterator("Scala") with RichIterator
+ val richStringIter = new RichStringIter
+ richStringIter foreach println
+}
+```
+Новый класс `RichStringIter` включает `StringIterator` как суперкласс и `RichIterator` как примесь.
+
+Используя только одиночное наследование мы бы не могли добиться того же уровня гибкости.
diff --git a/_ru/tour/multiple-parameter-lists.md b/_ru/tour/multiple-parameter-lists.md
new file mode 100644
index 0000000000..d1938cb4b0
--- /dev/null
+++ b/_ru/tour/multiple-parameter-lists.md
@@ -0,0 +1,80 @@
+---
+layout: tour
+title: Множественные списки параметров (Каррирование)
+
+discourse: true
+
+partof: scala-tour
+
+num: 10
+language: ru
+next-page: case-classes
+previous-page: nested-functions
+
+---
+
+Методы могут объявляться с несколькими списками параметров. При этом когда такой метод вызывается с меньшим количеством списков параметров, это приводит к созданию новой функции, которая ожидает на вход не достающий список параметров. Формально это называется [частичное применение](https://en.wikipedia.org/wiki/Partial_application).
+
+Рассмотрим такие примеры из класса [Traversable](/overviews/collections/trait-traversable.html) коллекции Scala:
+
+```
+def foldLeft[B](z: B)(op: (B, A) => B): B
+```
+
+`foldLeft` применяет бинарный оператор `op` к начальному значению `z` и ко всем остальным элементам этого класса слева направо. Ниже приведен пример его использования.
+
+Начиная с начального значения 0, `foldLeft` применяет функцию `(m, n) => m + n` к каждому элементу списка и предыдущему накопленному значению.
+
+```tut
+val numbers = List(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
+val res = numbers.foldLeft(0)((m, n) => m + n)
+print(res) // 55
+```
+
+Множественные списки параметров имеют избыточный синтаксис, поэтому их следует использоваться экономно. Можем предложить следующие варианты для использования множественных списков (каррирования):
+
+#### Отдельный функциональный параметр
+ Функцию `op` можно выделить в отдельный функциональный параметр у `foldLeft`, благодаря такому выделению становится возможен более элегантный стиль передачи анонимной функции в метод. Без такого выделения код выглядел бы следующим образом:
+```
+numbers.foldLeft(0, {(m: Int, n: Int) => m + n})
+```
+
+ Обратите внимание, что использование отдельного функционального параметра позволяет нам использовать автоматическое выведение типа для него, что делает код еще более кратким, это было бы невозможно без каррирования.
+
+```
+numbers.foldLeft(0)(_ + _)
+```
+ Если в утверждении `numbers.foldLeft(0)(_ + _)` зафиксировать отдельный параметр `z`, мы получим частично определенную функцию, которую можно переиспользовать, как показано ниже:
+```tut
+val numbers = List(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
+val numberFunc = numbers.foldLeft(List[Int]())_ // z = Empty.List[Int]
+
+val squares = numberFunc((xs, x) => xs:+ x*x)
+print(squares.toString()) // List(1, 4, 9, 16, 25, 36, 49, 64, 81, 100)
+
+val cubes = numberFunc((xs, x) => xs:+ x*x*x)
+print(cubes.toString()) // List(1, 8, 27, 64, 125, 216, 343, 512, 729, 1000)
+```
+
+ `foldLeft` и `foldRight` может быть использован в любой из следующих вариаций,
+```tut
+val numbers = List(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
+
+numbers.foldLeft(0)((sum, item) => sum + item) // Общая Форма
+numbers.foldRight(0)((sum, item) => sum + item) // Общая Форма
+
+numbers.foldLeft(0)(_+_) // Форма с каррированием
+numbers.foldRight(0)(_+_) // Форма с каррированием
+
+(0 /: numbers)(_+_) // Используется вместо foldLeft
+(numbers :\ 0)(_+_) // Используется вместо foldRight
+```
+
+
+#### Неявные параметры
+ Чтоб указать что параметр используется неявно (`implicit`) необходимо задавать несколько списков параметров. Примером может служить следующее:
+
+```
+def execute(arg: Int)(implicit ec: ExecutionContext) = ???
+```
+
diff --git a/_ru/tour/named-arguments.md b/_ru/tour/named-arguments.md
new file mode 100644
index 0000000000..defb9d4282
--- /dev/null
+++ b/_ru/tour/named-arguments.md
@@ -0,0 +1,34 @@
+---
+layout: tour
+title: Именованные Аргументы
+
+discourse: true
+
+partof: scala-tour
+
+num: 34
+language: ru
+next-page: packages-and-imports
+previous-page: default-parameter-values
+prerequisite-knowledge: function-syntax
+
+---
+
+При вызове методов можно конкретно указывать название задаваемого аргумента следующим образом:
+
+```tut
+def printName(first: String, last: String): Unit = {
+ println(first + " " + last)
+}
+
+printName("John", "Smith") // Prints "John Smith"
+printName(first = "John", last = "Smith") // Prints "John Smith"
+printName(last = "Smith", first = "John") // Prints "John Smith"
+```
+Обратите внимание, что при указании имени параметра, порядок аргумента может быть изменен. Однако если какие-то аргументы именованного, а другие нет, то аргументы без имени должны стоять на первом месте и располагаться в том порядке, в котором описаны параметры метода.
+
+```tut:fail
+printName(last = "Smith", "john") // ошибка: позиция после именованного аргумента
+```
+
+Обратите внимание, что именованные аргументы не работают при вызове Java методов.
diff --git a/_ru/tour/nested-functions.md b/_ru/tour/nested-functions.md
new file mode 100644
index 0000000000..ef082c36e4
--- /dev/null
+++ b/_ru/tour/nested-functions.md
@@ -0,0 +1,38 @@
+---
+layout: tour
+title: Вложенные Методы
+
+discourse: true
+
+partof: scala-tour
+
+num: 9
+language: ru
+next-page: multiple-parameter-lists
+previous-page: higher-order-functions
+
+---
+
+В Scala возможно объявление метода вкладывать в тело другого метода. Это реализовано в следующем примере, в котором метод `factorial` используется для вычисления факториала заданного числа:
+
+{% scalafiddle %}
+```tut
+ def factorial(x: Int): Int = {
+ def fact(x: Int, accumulator: Int): Int = {
+ if (x <= 1) accumulator
+ else fact(x - 1, x * accumulator)
+ }
+ fact(x, 1)
+ }
+
+ println("Factorial of 2: " + factorial(2))
+ println("Factorial of 3: " + factorial(3))
+```
+{% endscalafiddle %}
+
+Результат выполнения программы:
+
+```
+Factorial of 2: 2
+Factorial of 3: 6
+```
diff --git a/_ru/tour/operators.md b/_ru/tour/operators.md
new file mode 100644
index 0000000000..1609ce60f5
--- /dev/null
+++ b/_ru/tour/operators.md
@@ -0,0 +1,81 @@
+---
+layout: tour
+title: Операторы
+
+discourse: true
+
+partof: scala-tour
+
+num: 30
+language: ru
+next-page: by-name-parameters
+previous-page: type-inference
+prerequisite-knowledge: case-classes
+
+---
+В Скале операторы - это обычные методы. В качестве _инфиксного оператора_ может быть использован любой метод с одним параметром. Например, `+` может вызываться с использованием точки:
+```
+10.+(1)
+```
+
+Однако легче воспринимать код, когда такие методы записаны как инфиксный оператор:
+```
+10 + 1
+```
+
+## Создание и использование операторов
+В качестве оператора можно использовать любой допустимый символ. Включая имена на подобии `add` или символ (символы) типа `+`.
+```tut
+case class Vec(val x: Double, val y: Double) {
+ def +(that: Vec) = new Vec(this.x + that.x, this.y + that.y)
+}
+
+val vector1 = Vec(1.0, 1.0)
+val vector2 = Vec(2.0, 2.0)
+
+val vector3 = vector1 + vector2
+vector3.x // 3.0
+vector3.y // 3.0
+```
+У класса Vec есть метод `+`, который мы использовали для добавления `vector1` и `vector2`. Используя круглые скобки, можно строить сложные выражения с читаемым синтаксисом. Пример создания класса `MyBool`, которое включает в себя методы `and` и `or`
+
+```tut
+case class MyBool(x: Boolean) {
+ def and(that: MyBool): MyBool = if (x) that else this
+ def or(that: MyBool): MyBool = if (x) this else that
+ def negate: MyBool = MyBool(!x)
+}
+```
+
+Теперь можно использовать операторы `and` и `or` в качестве инфиксных операторов:
+
+```tut
+def not(x: MyBool) = x.negate
+def xor(x: MyBool, y: MyBool) = (x or y) and not(x and y)
+```
+
+Это помогает сделать объявление `xor` более читабельным.
+
+## Порядок очередности
+Когда выражение использует несколько операторов, операторы оцениваются на основе приоритета первого символа. Таблица приоритетов символов:
+```
+(символы которых нет снизу)
+* / %
++ -
+:
+= !
+< >
+&
+^
+|
+(буквы)
+```
+Такой приоритет распространяется на любые функции, которые вы задаете. Например, следующее выражение:
+```
+a + b ^? c ?^ d less a ==> b | c
+```
+эквивалентно
+```
+((a + b) ^? (c ?^ d)) less ((a ==> b) | c)
+```
+`?^` имеет высший приоритет, потому что начинается с символа `?`. Второй по старшинству приоритет имеет `+`, за которым следуют `==>`, `^?`, `|`, и `less`.
diff --git a/_ru/tour/package-objects.md b/_ru/tour/package-objects.md
new file mode 100644
index 0000000000..43cc9c85da
--- /dev/null
+++ b/_ru/tour/package-objects.md
@@ -0,0 +1,72 @@
+---
+layout: tour
+title: Объекты Пакета
+
+discourse: true
+
+partof: scala-tour
+
+num: 36
+language: ru
+previous-page: packages-and-imports
+---
+
+# Объекты Пакета
+
+У каждого пакета может существовать связанный с этим пакетом объект (package object), общий для всех членов пакета. Такой объект может быть только один. Любые выражения, содержащиеся в объекте пакета, считаются членами самого пакета.
+
+Объекты пакета могут содержать произвольные виды выражений, а не только переменные и методы. Например, они часто используются для хранения псевдонимов типа и наборов неявных преобразований доступных всему пакету. Объекты пакета могут также наследоваться от классов и трейтов Scala.
+
+По соглашению, исходный код объекта пакета обычно помещается в файл под названием `package.scala`.
+
+См. пример ниже. Предположим, есть старший класс `Fruit` и три наследуемых от него объекта `Fruit` в пакете.
+
+`gardening.fruits`:
+
+```
+// в файле gardening/fruits/Fruit.scala
+package gardening.fruits
+
+case class Fruit(name: String, color: String)
+object Apple extends Fruit("Apple", "green")
+object Plum extends Fruit("Plum", "blue")
+object Banana extends Fruit("Banana", "yellow")
+```
+
+Теперь предположим, что мы хотим поместить переменную `planted` и метод `showFruit` непосредственно в пакет `gardening`.
+Вот как это делается:
+
+```
+// в файле gardening/fruits/package.scala
+package gardening
+package object fruits {
+ val planted = List(Apple, Plum, Banana)
+ def showFruit(fruit: Fruit): Unit = {
+ println(s"${fruit.name}s are ${fruit.color}")
+ }
+}
+```
+
+Для примера, следующий объект `PrintPlanted` импортирует `planted` и `showFruit` точно так же, как с вариантом импорта класса `Fruit`, используя групповой стиль импорта пакета gardening.fruits:
+
+```
+// в файле PrintPlanted.scala
+import gardening.fruits._
+object PrintPlanted {
+ def main(args: Array[String]): Unit = {
+ for (fruit <- fruits.planted) {
+ showFruit(fruit)
+ }
+ }
+}
+```
+
+Объекты пакета ведут себя также, как и любые другие объекты. Это означает, что вы можете использовать наследование, при этом сразу нескольких трейтов:
+
+```
+package object fruits extends FruitAliases with FruitHelpers {
+ // здесь располагаются вспомогательные классы и переменные
+}
+```
+
+Обратите внимание, что перегрузка метода не работает в объектах пакета.
diff --git a/_ru/tour/packages-and-imports.md b/_ru/tour/packages-and-imports.md
new file mode 100644
index 0000000000..ef7865e3e7
--- /dev/null
+++ b/_ru/tour/packages-and-imports.md
@@ -0,0 +1,86 @@
+---
+layout: tour
+title: Пакеты и Импорт
+
+discourse: true
+
+partof: scala-tour
+
+num: 35
+language: ru
+previous-page: named-arguments
+next-page: package-objects
+---
+
+# Пакеты и Импорт
+Scala использует пакеты для указания пространства имен, они позволяют создавать модульную структуру кода.
+
+## Создание пакета
+Пакеты создаются путем объявления одного или нескольких имен пакетов в верхней части файла Scala.
+
+```
+package users
+
+class User
+```
+По соглашению пакеты называют тем же именем, что и каталог, содержащий файл Scala. Однако Scala не обращает внимания на расположение файлов. Структура каталогов sbt-проекта для `package users` может выглядеть следующим образом:
+```
+- ExampleProject
+ - build.sbt
+ - project
+ - src
+ - main
+ - scala
+ - users
+ User.scala
+ UserProfile.scala
+ UserPreferences.scala
+ - test
+```
+Обратите внимание, что каталог `users` находится внутри каталога `scala` и как в пакете содержатся несколько файлов Scala. Каждый файл Scala в пакете может иметь одно и то же объявление пакета. Другой способ объявления пакетов - с помощью фигурных скобок:
+```
+package users {
+ package administrators {
+ class NormalUser
+ }
+ package normalusers {
+ class NormalUser
+ }
+}
+```
+Как видите, такой способ позволяет вкладывать пакеты друг в друга, а также обеспечивает отличный контроль за областью видимости и возможностью изоляции.
+
+Имя пакета должно быть все в нижнем регистре, и если код разрабатывается в организации имеющей сайт, то следует использовать имя следующего формата: `<домен-верхнего-уровня>.<доменное-имя>.<название-проекта>`. Например, если бы у Google был проект под названием `SelfDrivingCar`, название пакета выглядело бы следующим образом:
+```
+package com.google.selfdrivingcar.camera
+
+class Lens
+```
+Что может соответствовать следующей структуре каталога: `SelfDrivingCar/src/main/scala/com/google/selfdrivingcar/camera/Lens.scala`.
+
+## Импорт
+Указание `import` открывает доступ к членам (классам, трейтам, функциям и т.д.) в других пакетах. Указание `import` не требуется для доступа к членам одного и того же пакета. Указание `import` избирательны:
+```
+import users._ // групповой импорт всего пакета users
+import users.User // импортировать только User
+import users.{User, UserPreferences} // импортировать только User, UserPreferences
+import users.{UserPreferences => UPrefs} // импортировать и переименовать
+```
+
+Одним из отличий Scala от Java является то, что импорт можно использовать где угодно:
+
+```tut
+def sqrtplus1(x: Int) = {
+ import scala.math.sqrt
+ sqrt(x) + 1.0
+}
+```
+В случае возникновения конфликта имен и необходимости импортировать что-либо из корня проекта, имя пакета должно начинаться с префикса `_root_`:
+```
+package accounts
+
+import _root_.users._
+```
+
+
+Примечание: Пакеты `scala` и `java.lang`, а также `object Predef` импортируются по умолчанию.
diff --git a/_ru/tour/pattern-matching.md b/_ru/tour/pattern-matching.md
new file mode 100644
index 0000000000..9a46a74005
--- /dev/null
+++ b/_ru/tour/pattern-matching.md
@@ -0,0 +1,151 @@
+---
+layout: tour
+title: Сопоставление с примером
+
+discourse: true
+
+partof: scala-tour
+
+num: 12
+language: ru
+next-page: singleton-objects
+previous-page: case-classes
+prerequisite-knowledge: case-classes, string-interpolation, subtyping
+
+---
+
+Сопоставление с примером (Pattern matching) - это механизм сравнения значений с определенным примером. При успешном совпадении значение может быть разложено на составные части. Мы рассматриваем сопоставление с примером, как более мощную версию `switch` оператора из Java. Eго также можно использовать вместо серии if/else выражений.
+
+## Синтаксис
+Синтаксис сопоставления с примером состоит из значения, ключевого слова `match` (сопоставить) и по крайней мере, одного пункта с примером `case`, с которым мы хотим сопоставить наше значение.
+```tut
+import scala.util.Random
+
+val x: Int = Random.nextInt(10)
+
+x match {
+ case 0 => "zero"
+ case 1 => "one"
+ case 2 => "two"
+ case _ => "many"
+}
+```
+Значение константы `x` выше представляет собой случайное целое число от 0 до 10. `x` становится левым операндом оператора `match`, а справа - выражением с четырьмя примерами (называемые еще _вариантами_). Последний вариант `_` - позволяет "поймать все оставшиеся варианты" т. е. для любого числа больше 2.
+
+Сопоставление с примером возвращает значение.
+```tut
+def matchTest(x: Int): String = x match {
+ case 1 => "one"
+ case 2 => "two"
+ case _ => "many"
+}
+matchTest(3) // many
+matchTest(1) // one
+```
+Это сопоставляющее выражение имеет тип String, так как все варианты сопоставления возвращают String. Поэтому функция `matchTest` возвращает String.
+
+## Сопоставление с классами образцами
+
+Классы образцы особенно полезны для сопоставления.
+
+```tut
+abstract class Notification
+
+case class Email(sender: String, title: String, body: String) extends Notification
+
+case class SMS(caller: String, message: String) extends Notification
+
+case class VoiceRecording(contactName: String, link: String) extends Notification
+
+
+```
+`Notification` - абстрактный суперкласс, от которого наследуются три конкретных типа реализаций классов образцов `Email`, `SMS`, и `VoiceRecording`. Теперь мы можем делать сопоставление с примером используя в качестве примера один из этих классов образцов.
+При сопоставлении с классом образцом мы можем сразу извлекать параметры из которых состоит класс (благодаря автоматическому использованию [объекта экстрактора](extractor-objects.html)):
+
+```
+def showNotification(notification: Notification): String = {
+ notification match {
+ case Email(email, title, _) =>
+ s"You got an email from $email with title: $title"
+ case SMS(number, message) =>
+ s"You got an SMS from $number! Message: $message"
+ case VoiceRecording(name, link) =>
+ s"you received a Voice Recording from $name! Click the link to hear it: $link"
+ }
+}
+val someSms = SMS("12345", "Are you there?")
+val someVoiceRecording = VoiceRecording("Tom", "voicerecording.org/id/123")
+
+println(showNotification(someSms)) // выводит "You got an SMS from 12345! Message: Are you there?"
+
+println(showNotification(someVoiceRecording)) // выводит "you received a Voice Recording from Tom! Click the link to hear it: voicerecording.org/id/123"
+```
+Функция `showNotification` принимает в качестве параметра абстрактный тип `Notification` который проверяет по образцам (т.е. выясняет, является ли он классом `Email`, `SMS` или `VoiceRecording`). В `case Email(email, title, _)`поля `email` и `title` используются в возвращаемом значении, а вот поле `body` игнорируется благодаря символу `_`.
+
+## Ограждения примеров
+Ограждения примеров - это просто логические выражения, которые используются для того, чтобы сделать выбор более специфичным (убрать лишние варианты). Просто добавьте `if <логическое выражение>` после примера.
+```
+
+def showImportantNotification(notification: Notification, importantPeopleInfo: Seq[String]): String = {
+ notification match {
+ case Email(email, _, _) if importantPeopleInfo.contains(email) =>
+ "You got an email from special someone!"
+ case SMS(number, _) if importantPeopleInfo.contains(number) =>
+ "You got an SMS from special someone!"
+ case other =>
+ showNotification(other) // в этом варианте считается подходящими параметры любого типа. Значит этот вариант выполняется во всех случаях и передает исходный параметр в функцию showNotification
+ }
+}
+
+val importantPeopleInfo = Seq("867-5309", "jenny@gmail.com")
+
+val someSms = SMS("867-5309", "Are you there?")
+val someVoiceRecording = VoiceRecording("Tom", "voicerecording.org/id/123")
+val importantEmail = Email("jenny@gmail.com", "Drinks tonight?", "I'm free after 5!")
+val importantSms = SMS("867-5309", "I'm here! Where are you?")
+
+println(showImportantNotification(someSms, importantPeopleInfo))
+println(showImportantNotification(someVoiceRecording, importantPeopleInfo))
+println(showImportantNotification(importantEmail, importantPeopleInfo))
+println(showImportantNotification(importantSms, importantPeopleInfo))
+```
+
+В варианте `case Email(email, _, _) if importantPeopleInfo.contains(email)`, пример сравнивается только если `email` находится в списке `importantPeopleInfo`.
+
+## Сопоставление только с типом
+Вы можете сопоставлять только по типу как в примере:
+```tut
+abstract class Device
+case class Phone(model: String) extends Device{
+ def screenOff = "Turning screen off"
+}
+case class Computer(model: String) extends Device {
+ def screenSaverOn = "Turning screen saver on..."
+}
+
+def goIdle(device: Device) = device match {
+ case p: Phone => p.screenOff
+ case c: Computer => c.screenSaverOn
+}
+```
+метод `goIdle` реализует изменение поведения в зависимости от типа `Device`. По соглашению в качестве названия варианта используется первая буква типа (в данном случае `p` и `c`).
+
+## Запечатанные классы
+Трейты и классы могут быть помечены как `sealed` это означает, что подтипы должны быть объявлены в одном файле, гарантируя тем самым, что все подтипы будут известны.
+
+```tut
+sealed abstract class Furniture
+case class Couch() extends Furniture
+case class Chair() extends Furniture
+
+def findPlaceToSit(piece: Furniture): String = piece match {
+ case a: Couch => "Lie on the couch"
+ case b: Chair => "Sit on the chair"
+}
+```
+Это полезно для сопоставления с примером, ведь мы будем заранее знать все доступные варианты и нам не нужен вариант "все остальные".
+
+## Замечания
+
+Сопоставление с примером наиболее полезно для сопоставления алгебраических типов, выраженных через [классы образцы](case-classes.html).
+Scala также позволяет создавать образцы независимо от классов образцов, через использование метода `unapply` в [объектах экстракторах](extractor-objects.html).
diff --git a/_ru/tour/polymorphic-methods.md b/_ru/tour/polymorphic-methods.md
new file mode 100644
index 0000000000..a430aaf654
--- /dev/null
+++ b/_ru/tour/polymorphic-methods.md
@@ -0,0 +1,36 @@
+---
+layout: tour
+title: Полиморфные методы
+
+discourse: true
+
+partof: scala-tour
+
+num: 28
+language: ru
+next-page: type-inference
+previous-page: implicit-conversions
+prerequisite-knowledge: unified-types
+
+---
+
+Также как и у обобщенных классов, у методов есть полиморфизм по типу, с таким же синтаксисом (параметр типа указывается в квадратных скобках сразу после названия метода).
+
+Вот пример:
+
+```tut
+def listOfDuplicates[A](x: A, length: Int): List[A] = {
+ if (length < 1)
+ Nil
+ else
+ x :: listOfDuplicates(x, length - 1)
+}
+println(listOfDuplicates[Int](3, 4)) // List(3, 3, 3, 3)
+println(listOfDuplicates("La", 8)) // List(La, La, La, La, La, La, La, La)
+```
+
+Метод `listOfDuplicates` принимает параметр типа `A` и параметры значений `x` и `length`. Значение `x` имеет тип `A`. Если `length < 1` мы возвращаем пустой список. В противном случае мы добавляем `x`к списку, которые возвращаем через рекурсивный вызовов. (Обратите внимание, что `::` означает добавление элемента слева к списку справа).
+
+В первом вызове метода мы явно указываем параметр типа, записывая `[Int]`. Поэтому первым аргументом должен быть `Int` и тип возвращаемого значения будет `List[Int]`.
+
+Во втором вызове показано, что вам не всегда нужно явно указывать параметр типа. Часто компилятор сам может вывести тип исходя из контекста или типа передаваемых аргументов. В этом варианте `"La"` - это `String`, поэтому компилятор знает, что `A` должен быть `String`.
diff --git a/_ru/tour/regular-expression-patterns.md b/_ru/tour/regular-expression-patterns.md
new file mode 100644
index 0000000000..32877a0106
--- /dev/null
+++ b/_ru/tour/regular-expression-patterns.md
@@ -0,0 +1,61 @@
+---
+layout: tour
+title: Регулярные Выражения
+
+discourse: true
+
+partof: scala-tour
+
+num: 15
+language: ru
+next-page: extractor-objects
+previous-page: singleton-objects
+
+---
+
+Регулярные выражения (Regular expression) - это специальный шаблон для поиска данных задаваемый в виде текстовой строки. Любая строка может быть преобразована в регулярное выражение методом `.r`.
+
+```tut
+import scala.util.matching.Regex
+
+val numberPattern: Regex = "[0-9]".r
+
+numberPattern.findFirstMatchIn("awesomepassword") match {
+ case Some(_) => println("Password OK")
+ case None => println("Password must contain a number")
+}
+```
+
+В приведенном выше примере `numberPattern` - это `Regex` (регулярное выражение), которое мы используем, чтобы убедиться, что пароль содержит число.
+
+Используя круглые скобки можно объединять сразу несколько групп регулярных выражений.
+
+```tut
+import scala.util.matching.Regex
+
+val keyValPattern: Regex = "([0-9a-zA-Z-#() ]+): ([0-9a-zA-Z-#() ]+)".r
+
+val input: String =
+ """background-color: #A03300;
+ |background-image: url(img/header100.png);
+ |background-position: top center;
+ |background-repeat: repeat-x;
+ |background-size: 2160px 108px;
+ |margin: 0;
+ |height: 108px;
+ |width: 100%;""".stripMargin
+
+for (patternMatch <- keyValPattern.findAllMatchIn(input))
+ println(s"key: ${patternMatch.group(1)} value: ${patternMatch.group(2)}")
+```
+Здесь мы обработали сразу и ключи и значения строки. В каждой совпадении есть подгруппа совпадений. Вот как выглядит результат:
+```
+key: background-color value: #A03300
+key: background-image value: url(img
+key: background-position value: top center
+key: background-repeat value: repeat-x
+key: background-size value: 2160px 108px
+key: margin value: 0
+key: height value: 108px
+key: width value: 100
+```
diff --git a/_ru/tour/self-types.md b/_ru/tour/self-types.md
new file mode 100644
index 0000000000..ccc896b0ec
--- /dev/null
+++ b/_ru/tour/self-types.md
@@ -0,0 +1,40 @@
+---
+layout: tour
+title: Самоописываемые типы
+
+discourse: true
+
+partof: scala-tour
+
+num: 25
+language: ru
+next-page: implicit-parameters
+previous-page: compound-types
+topics: self-types
+prerequisite-knowledge: nested-classes, mixin-class-composition
+
+---
+Самоописываемый тип(Self type) - это способ объявить, что трейт должен быть смешан с другим трейтом, даже если он не расширяет его напрямую. Что открывает доступ к членам зависимости без импортирования.
+
+Самоописываемый тип - это способ сузить тип `this` или другого идентификатора, который ссылается на `this`. Синтаксис похож на синтаксис обычной функции, но означает кое-что иное.
+
+Чтобы использовать самоописываемый тип в трейте напишите: идентификатор, тип другого трейта, который хотите добавить и `=>` (например, `someIdentifier: SomeOtherTrait =>`).
+```tut
+trait User {
+ def username: String
+}
+
+trait Tweeter {
+ this: User => // переназначил this
+ def tweet(tweetText: String) = println(s"$username: $tweetText")
+}
+
+class VerifiedTweeter(val username_ : String) extends Tweeter with User { // Мы добавили User потому этого требует Tweeter
+ def username = s"real $username_"
+}
+
+val realBeyoncé = new VerifiedTweeter("Beyoncé")
+realBeyoncé.tweet("Just spilled my glass of lemonade") // выведет "real Beyoncé: Just spilled my glass of lemonade"
+```
+
+Поскольку мы указали `this: User =>` в трейте `Tweeter`, теперь переменная `username` находится в пределах видимости для метода `tweet`. Это также означает что `VerifiedTweeter` при наследовании от `Tweeter` должен быть смешан с `User` (используя `with User`).
diff --git a/_ru/tour/singleton-objects.md b/_ru/tour/singleton-objects.md
new file mode 100644
index 0000000000..eab6688c75
--- /dev/null
+++ b/_ru/tour/singleton-objects.md
@@ -0,0 +1,107 @@
+---
+layout: tour
+title: Объекты Одиночки
+
+discourse: true
+
+partof: scala-tour
+
+num: 13
+language: ru
+next-page: regular-expression-patterns
+previous-page: pattern-matching
+prerequisite-knowledge: classes, methods, private-methods, packages, option
+---
+Все объекты являются одиночками (Singleton Object) - то есть существуют в единственном экземпляре. Он создается лениво, когда на него ссылаются, также как ленивые значения (lazy val).
+
+На самом верхнем уровне объект является одиночкой.
+
+Как член класса или как локальная переменная, он ведет себя точно так же как ленивое значение (lazy val).
+# Объявление одиночного объекта
+Объект - является значением. Объявление объекта происходит схожим с классом образом, но используется ключевое слово `object`:
+```tut
+object Box
+```
+
+Вот пример объекта с методом:
+```
+package logging
+
+object Logger {
+ def info(message: String): Unit = println(s"INFO: $message")
+}
+```
+Метод `info` может быть импортирован в любом месте программы. Создание подобных методов является распространенным вариантом использования одиночных объектов.
+
+Давайте посмотрим, как использовать `info` в другом пакете:
+
+```
+import logging.Logger.info
+
+class Project(name: String, daysToComplete: Int)
+
+class Test {
+ val project1 = new Project("TPS Reports", 1)
+ val project2 = new Project("Website redesign", 5)
+ info("Created projects") // Prints "INFO: Created projects"
+}
+```
+
+Метод `info` виден благодаря указанию импорта `import logging.Logger.info`.
+
+Замечание: Если `object` не является объектом верхнего уровня, но вложен в другой класс или объект, то объект, как и любой другой член, "зависим от пути".
+
+## Объекты компаньоны
+
+Объект с тем же именем, что и класс называется _объект компаньон_ (companion object). И наоборот, класс является классом-компаньоном объекта. Класс или объект компаньон может получить доступ к приватным членам своего спутника. Используйте объект компаньон для методов и значений, которые не специфичны для экземпляров класса компаньона.
+```
+import scala.math._
+
+case class Circle(radius: Double) {
+ import Circle._
+ def area: Double = calculateArea(radius)
+}
+
+object Circle {
+ private def calculateArea(radius: Double): Double = Pi * pow(radius, 2.0)
+}
+
+val circle1 = new Circle(5.0)
+
+circle1.area
+```
+
+Класс `Circle` имеет член `area`, который специфичен для каждого конкретного экземпляра, а метод `calculateArea` одиночного объекта `Circle`, доступен для каждого экземпляра класса `Circle`.
+
+Объект компаньон может также содержать методы создающие конкретные экземпляры класса спутника:
+```tut
+class Email(val username: String, val domainName: String)
+
+object Email {
+ def fromString(emailString: String): Option[Email] = {
+ emailString.split('@') match {
+ case Array(a, b) => Some(new Email(a, b))
+ case _ => None
+ }
+ }
+}
+
+val scalaCenterEmail = Email.fromString("scala.center@epfl.ch")
+scalaCenterEmail match {
+ case Some(email) => println(
+ s"""Registered an email
+ |Username: ${email.username}
+ |Domain name: ${email.domainName}
+ """)
+ case None => println("Error: could not parse email")
+}
+```
+`object Email` содержит производящий метод `fromString`, который создает экземпляр `Email` из строки. Мы возвращаем результат как `Option[Email]` на случай возникновения ошибок парсинга.
+
+Примечание: Если у класса или объекта есть компаньон, они должны быть размещены в одном и том же файле. Чтобы задать компаньонов в REPL, либо определите их на той же строке, либо перейдите в режим `:paste`.
+
+## Примечания для Java-программистов ##
+
+`static` члены в Java смоделированы как обычные члены объекта компаньона в Scala.
+
+При использовании объекта компаньона из Java-кода, члены будут определены в сопутствующем классе компаньоне с `static` модификатором. Это называется _пробрасывание статики_. Такое происходит, даже если вы сами не определили класс компаньон.
diff --git a/_ru/tour/tour-of-scala.md b/_ru/tour/tour-of-scala.md
new file mode 100644
index 0000000000..a2e6cc805f
--- /dev/null
+++ b/_ru/tour/tour-of-scala.md
@@ -0,0 +1,64 @@
+---
+layout: tour
+title: Введение
+
+discourse: true
+
+partof: scala-tour
+
+num: 1
+language: ru
+next-page: basics
+---
+
+## Добро пожаловать к обзору
+Здесь вы увидите вводное описание наиболее часто используемых возможностей Scala.
+Этот обзор предназначен для новичков в изучении языка.
+
+Это лишь небольшая экскурсия, а не полный курс освоения языка. Для глубокого погружения рекомендуем почитать [книги](/books.html) или воспользоваться курсами
+[на других ресурсах](/learn.html).
+
+## Что такое Scala?
+Scala - это современный мультипарадигмальный язык программирования, разработанный для выражения общих концепций программирования в простой, удобной и типобезопасной манере. Элегантно объединяя особенности объектно-ориентированных и функциональных языков.
+
+## Scala объектно ориентированный ##
+Scala - это чистый объектно-ориентированный язык в том смысле, что [каждое значение - это объект](unified-types.html). Типы и поведение объектов описаны в [классах](classes.html) и [трейтах](traits.html)(характеристиках объектов). Классы расширяются за счет механизма наследования и гибкого [смешивания классов](mixin-class-composition.html), который используется для замены множественного наследования.
+
+## Scala функциональный ##
+Scala также является функциональным языком в том смысле, что [каждая функция - это значение](unified-types.html). Scala предоставляет [легкий синтаксис](basics.html) для определения анонимных функций, поддерживает [функции высшего порядка](higher-order-functions.html), поддерживает [вложенные функции](nested-functions.html), а также [каррирование](multiple-parameter-lists.html). Scala имеют встроенную поддержку алгебраических типов данных, которые используются в большинстве функциональных языках программирования (эта поддержка базируется на механизме [сопоставления с примером](pattern-matching.html), где в качестве примера выступают [классы образцы](case-classes.html) ). [Объекты](singleton-objects.html) предоставляют удобный способ группировки функций, не входящих в класс.
+
+Вдобавок к этому, концепция сопоставления с примером логично переносится на [обработку XML-данных](https://github.com/scala/scala-xml/wiki/XML-Processing) используя в качестве примера [регулярные выражения](regular-expression-patterns.html), при поддержке функционала [объектов экстракторов](extractor-objects.html). Для еще большего удобства обработки данных представлена схема формирования запросов с использованием [for-выражения](for-comprehensions.html). Такие возможности делают Scala идеальным решением для разработки приложений по типу веб-сервисов.
+
+## Scala статически типизированный ##
+Scala оснащен выразительной системой типов, которая обеспечивает безопасное и гармоничное использование абстракций. В частности, система типов поддерживает:
+
+* [обобщенные классы](generic-classes.html)
+* [вариантность типов](variances.html)
+* [верхние](upper-type-bounds.html) и [нижние](lower-type-bounds.html) границы типов
+* [внутренние классы](inner-classes.html) и [члены абстрактного типа](abstract-type-members.html), как часть объектов
+* [составные типы](compound-types.html)
+* [самоописываемые типы](self-types.html)
+* [неявные параметры](implicit-parameters.html) и [неявные преобразования](implicit-conversions.html)
+* [полиморфные методы](polymorphic-methods.html)
+
+[Выведение типов](type-inference.html) означает, что разработчику не обязательно добавлять в код избыточную информацию о типах.
+Такой функционал обеспечивает основу для безопасного переиспользования абстракций и типобезопасного развития программного обеспечения.
+
+## Scala расширяемый ##
+
+Зачастую разработка приложений для очень специфичных областей требует специфичных для этих областей языковых возможностей, либо отдельных специализированных языков программирования. Вместо этого Scala предлагает уникальные механизмы, для легкой модификации и расширения самого языка.
+
+Во многих случаях такое можно сделать без использования средств мета-программирования, таких как макросы. Например:
+
+* [Неявные классы](http://docs.scala-lang.org/overviews/core/implicit-classes.html) позволяют добавлять новые методы к уже существующим.
+* [Интерполяция строк](/overviews/core/string-interpolation.html) позволяет добавлять обработку строк (расширяется разработчиком с помощью интерполяторов).
+
+## Scala совместимый
+
+Scala полностью совместим с популярной средой Java Runtime Environment (JRE). Взаимодействие с основным объектно-ориентированным языком программирования Java происходит максимально гладко. Новые функции Java, такие как SAM, [лямбды](higher-order-functions.html), [аннотации](annotations.html) и [дженерики](generic-classes.html), имеют прямые аналоги в Scala.
+
+Те функции Scala, которые не имеют аналогов в Java, такие как [параметры по умолчанию](default-parameter-values.html) и [именованные параметры](named-arguments.html), компилируются как можно ближе к Java. Scala имеет такую же компиляционную модель (отдельная компиляция, динамическая загрузка классов), как у Java, что позволяет получить доступ к тысячам уже существующих высококачественных библиотек.
+
+## Наслаждайтесь туром!
+
+Для продолжения знакомства предлагаю перейти на [следующую страницу](basics.html) нашего тура.
\ No newline at end of file
diff --git a/_ru/tour/traits.md b/_ru/tour/traits.md
new file mode 100644
index 0000000000..4fea28e80f
--- /dev/null
+++ b/_ru/tour/traits.md
@@ -0,0 +1,84 @@
+---
+layout: tour
+title: Трейты
+
+discourse: true
+
+partof: scala-tour
+
+num: 5
+language: ru
+next-page: tuples
+previous-page: classes
+topics: traits
+prerequisite-knowledge: expressions, classes, generics, objects, companion-objects
+
+---
+
+Трейты (Traits) используются чтоб обмениваться между классами информацией о структуре и полях. Они похожи на интерфейсы из Java 8. Классы и объекты могут расширять трейты, но трейты не могут быть созданы и поэтому не имеют параметров.
+
+## Объявление трейта
+Минимальное объявление трейта - это просто ключевое слово `trait` и его имя:
+
+```tut
+trait HairColor
+```
+
+Трейты наиболее полезны в качестве обобщенного типа с абстрактными методами.
+```tut
+trait Iterator[A] {
+ def hasNext: Boolean
+ def next(): A
+}
+```
+
+При наследовании от трейта `Iterator[A]` требует указание типа `A` а также реализация методов `hasNext` и `next`.
+
+## Использование трейтов
+Чтоб использовать трейты, необходимо наследовать класс от него используя ключевое слово `extends`. Затем необходимо реализовать все абстрактные члены трейта, используя ключевое слово `override`:
+```tut
+trait Iterator[A] {
+ def hasNext: Boolean
+ def next(): A
+}
+
+class IntIterator(to: Int) extends Iterator[Int] {
+ private var current = 0
+ override def hasNext: Boolean = current < to
+ override def next(): Int = {
+ if (hasNext) {
+ val t = current
+ current += 1
+ t
+ } else 0
+ }
+}
+
+
+val iterator = new IntIterator(10)
+iterator.next() // вернет 0
+iterator.next() // вернет 1
+```
+Этот класс `IntIterator` использует параметр `to` в качестве верхней границы. Он наследуется от `Iterator[Int]`, что означает, что метод `next` должен возвращать Int.
+
+## Подтипы
+Туда где требуется определенный тип трейта, мы можем передавать любой наследованный от требуемого трейта класс
+```tut
+import scala.collection.mutable.ArrayBuffer
+
+trait Pet {
+ val name: String
+}
+
+class Cat(val name: String) extends Pet
+class Dog(val name: String) extends Pet
+
+val dog = new Dog("Harry")
+val cat = new Cat("Sally")
+
+val animals = ArrayBuffer.empty[Pet]
+animals.append(dog)
+animals.append(cat)
+animals.foreach(pet => println(pet.name)) // выведет "Harry" и "Sally"
+```
+У трейта `Pet` есть абстрактное поле `name`, которое реализовано в классах `Cat` and `Dog`. В последней строке мы вызываем `pet.name`, который должен быть реализован в любом подтипе унаследованным от трейта `Pet`.
diff --git a/_ru/tour/tuples.md b/_ru/tour/tuples.md
new file mode 100644
index 0000000000..094a76fbdf
--- /dev/null
+++ b/_ru/tour/tuples.md
@@ -0,0 +1,95 @@
+---
+layout: tour
+title: Кортежи
+
+discourse: true
+
+partof: scala-tour
+
+num: 6
+language: ru
+next-page: mixin-class-composition
+previous-page: traits
+topics: tuples
+
+---
+
+В Scala, кортеж (Тuple) это класс контейнер содержащий упорядоченный набор элементов различного типа.
+Кортежи неизменяемы.
+
+Кортежи могут пригодиться, когда нам нужно вернуть сразу несколько значений из функции.
+
+Кортеж может быть создан как:
+
+```tut
+val ingredient = ("Sugar" , 25):Tuple2[String, Int]
+```
+Такая запись создает кортеж размерности 2, содержащий пару элементов String и Int.
+
+Кортежи в Скале - представлены серией классов: Tuple2, Tuple3 и т.д., до Tuple22.
+Таким образом, создавая кортеж с n элементами (n лежащими между 2 и 22), Скала просто создает один из соответствующих классов, который параметризован типом входящих в состав элементов.
+
+В нашем примере, составляющие тип Tuple2[String, Int].
+
+## Доступ к элементам
+
+Доступ к элементам кортежа осуществляется при помощи синтаксиса подчеркивания.
+'tuple._n' дает n-ый элемент (столько, сколько существует элементов).
+
+```tut
+println(ingredient._1) // Sugar
+
+println(ingredient._2) // 25
+```
+
+## Распаковка данных кортежа
+
+Scala кортежи также поддерживают [распаковку](extractor-objects.html).
+
+```tut
+val (name, quantity) = ingredient
+
+println(name) // Sugar
+
+println(quantity) // 25
+```
+
+Распаковка данных кортежа может быть использована в [сопоставлении с примером](pattern-matching.html)
+
+```tut
+val planetDistanceFromSun = List(("Mercury", 57.9), ("Venus", 108.2), ("Earth", 149.6 ), ("Mars", 227.9), ("Jupiter", 778.3))
+
+planetDistanceFromSun.foreach{ tuple => {
+
+ tuple match {
+
+ case ("Mercury", distance) => println(s"Mercury is $distance millions km far from Sun")
+
+ case p if(p._1 == "Venus") => println(s"Venus is ${p._2} millions km far from Sun")
+
+ case p if(p._1 == "Earth") => println(s"Blue planet is ${p._2} millions km far from Sun")
+
+ case _ => println("Too far....")
+
+ }
+
+ }
+
+}
+```
+
+Или в ['for' выражении](for-comprehensions.html).
+
+```tut
+val numPairs = List((2, 5), (3, -7), (20, 56))
+
+for ((a, b) <- numPairs) {
+
+ println(a * b)
+
+}
+```
+
+Значение () типа Unit по свой сути совпадает со значением () типа Tuple0. Может быть только одно значение такого типа, так как в нём нет элементов.
+
+Иногда бывает трудно выбирать между кортежами и классами образцами. Как правило, классы образцы являются предпочтительным выбором, если класс-контейнер содержащий элементы сам по себе имеет значимый смысл.
diff --git a/_ru/tour/type-inference.md b/_ru/tour/type-inference.md
new file mode 100644
index 0000000000..3f936385fa
--- /dev/null
+++ b/_ru/tour/type-inference.md
@@ -0,0 +1,75 @@
+---
+layout: tour
+title: Выведение Типа
+
+discourse: true
+
+partof: scala-tour
+
+num: 29
+language: ru
+next-page: operators
+previous-page: polymorphic-methods
+---
+
+Компилятор Scala часто может вывести тип выражения, так что вам не нужно указывать его явным образом.
+
+## Не указывая тип
+
+```tut
+val businessName = "Montreux Jazz Café"
+```
+Компилятор может определить, что тип константы `businessName` является `String`. Аналогичным образом это работает и для методов:
+
+```tut
+def squareOf(x: Int) = x * x
+```
+Компилятор может определить, что возвращаемый тип является `Int`, поэтому явного указания типа не требуется.
+
+Для рекурсивных методов компилятор не в состоянии вывести тип. Вот программа, которая не скомпилируется по этой причине:
+
+```tut:fail
+def fac(n: Int) = if (n == 0) 1 else n * fac(n - 1)
+```
+
+Также необязательно указывать параметры типа при вызове [полиморфных методов](polymorphic-methods.html) или [обобщенных классов](generic-classes.html). Компилятор Scala определит тип параметра из контекста и из типов фактически передаваемых параметров метода/конструктора.
+
+Вот два примера:
+
+```tut
+case class MyPair[A, B](x: A, y: B);
+val p = MyPair(1, "scala") // тип: MyPair[Int, String]
+
+def id[T](x: T) = x
+val q = id(1) // тип: Int
+```
+
+Компилятор использует типы аргументов `MyPair` для определения типа `A` и `B`. Тоже самое для типа `x`.
+
+## Параметры
+
+Для параметров компилятор никогда не выводит тип. Однако, в некоторых случаях, он может вывести типы для параметров анонимной функции при передаче ее в качестве аргумента.
+
+```tut
+Seq(1, 3, 4).map(x => x * 2) // List(2, 6, 8)
+```
+
+Параметр у map - `f: A => B` (функциональный параметр переводящий тип из A в B). Поскольку мы разместили целые числа в нашей последовательности `Seq`, компилятор знает, что элемент `A` является `Int` (т.е. `x` является целым числом). Поэтому компилятор может определить из выражения `x * 2`, что результат (`B`) является типом `Int`.
+
+## Когда _не следует_ полагаться на выведение типа
+
+Обычно считается, наиболее удобочитаемым объявить тип членов, которые открыты для публичного использования через API. Поэтому мы рекомендуем вам явно указывать тип для любых API, которые будут доступны пользователям вашего кода.
+
+Кроме того, выведение может иногда приводить к слишком специфичному типу. Предположим, мы напишем:
+
+```tut
+var obj = null
+```
+
+Тогда мы не сможем далее сделать это переназначение:
+
+```tut:fail
+obj = new AnyRef
+```
+
+Такое не будет компилироваться, потому что для `obj` предполагался тип `Null`. Поскольку единственным значением этого типа является `null`, то невозможно присвоить другое значение.
\ No newline at end of file
diff --git a/_ru/tour/unified-types.md b/_ru/tour/unified-types.md
new file mode 100644
index 0000000000..521ff51754
--- /dev/null
+++ b/_ru/tour/unified-types.md
@@ -0,0 +1,82 @@
+---
+layout: tour
+title: Единобразие типов
+
+discourse: true
+
+partof: scala-tour
+
+num: 3
+language: ru
+next-page: classes
+previous-page: basics
+prerequisite-knowledge: classes, basics
+
+---
+
+В Scala все значения имеют тип, включая числовые значения и функции. Диаграмма ниже иллюстрирует подмножество иерархии типов.
+
+
+
+## Иерархия типов Scala ##
+
+[`Any`](http://www.scala-lang.org/api/2.12.1/scala/Any.html) это супертип всех типов, также называемый верхним типом. Он определяет несколько универсальных методов, таких как `equals`, `hashCode` и `toString`. У `Any` есть два прямых подкласса: `AnyVal` и `AnyRef`.
+
+`AnyVal` представляет числовые типы. Существует девять предварительно определенных числовых типов и они никогда не могут быть равны 'null': `Double`, `Float`, `Long`, `Int`, `Short`, `Byte`, `Char`, `Unit`, и `Boolean`. `Unit` - это числовой тип, который не содержит значимой информации (также обозначает пустое множество). Есть только один представитель типа `Unit`, который можно объявить вот так: `()`. Все функции должны возвращать что-то, поэтому иногда `Unit` полезный для возврата тип.
+
+`AnyRef` представляет ссылочные типы. Все типы, не относящиеся к "числовым типам", называются ссылочными типами. Каждый объявляемый пользователем тип в Scala является подтипом `AnyRef`. Если в Scala исходить из контекста среды исполнения Java, `AnyRef` соответствует `java.lang.Object`.
+
+Вот пример, демонстрирующий, что строки, целые числа, символы, логические значения и функции являются объектами, как и любой другой объект:
+
+```tut
+val list: List[Any] = List(
+ "a string",
+ 732, // целое число
+ 'c', // символ
+ true, // логическое значение
+ () => "анонимная функция возвращающая строку"
+)
+
+list.foreach(element => println(element))
+```
+
+Объявляем переменную `list` типа `List[Any]`. Список инициализируется элементами различных типов, но все они являются экземпляром `scala.Any`, так что вы можете добавить их в список.
+
+Ниже приведен вывод программы:
+
+```
+a string
+732
+c
+true
+
+```
+
+## Приведение типа
+Числовые типы могут быть приведены следующим образом:
+
+
+Например:
+
+```tut
+val x: Long = 987654321
+val y: Float = x // 9.8765434E8 (заметьте, что некоторая точность теряется в этом случае.)
+
+val face: Char = '☺'
+val number: Int = face // 9786
+```
+
+Приведение типа - однонаправленно. Следующий пример не скомпилируется:
+
+```
+val x: Long = 987654321
+val y: Float = x // 9.8765434E8
+val z: Long = y // обратно не подходит
+```
+
+Вы также можете приводить к своему подтипу. Об этом мы поговорим позже в ходе нашего обзора.
+
+## Nothing и Null
+`Nothing` является подтипом всех типов, также называемым нижним типом. Нет значения, которое имеет тип `Nothing`. Обычно он используется чтоб дать сигнал о не вычислимости, например брошено исключение, выход из программы, бесконечное зацикливание (т.е. это тип выражения, которое не вычисляется).
+
+`Null` подтип всех ссылочных типов (т.е. любой подтип AnyRef). Он имеет одно значение, определяемое ключевым словом литерала `null`. `Null` предоставляется в основном для функциональной совместимости с другими языками JVM и почти никогда не должен использоваться в коде Scala. Об альтернативах `null` мы поговорим позднее.
diff --git a/_ru/tour/upper-type-bounds.md b/_ru/tour/upper-type-bounds.md
new file mode 100644
index 0000000000..7446261c1a
--- /dev/null
+++ b/_ru/tour/upper-type-bounds.md
@@ -0,0 +1,54 @@
+---
+layout: tour
+title: Верхнее Ограничение Типа
+
+discourse: true
+
+partof: scala-tour
+categories: tour
+num: 20
+language: ru
+next-page: lower-type-bounds
+previous-page: variances
+
+---
+
+В Scala [параметры типа](generic-classes.html) и [члены абстрактного типа](abstract-type-members.html) могут быть ограничены определенными диапазонами. Такие диапазоны ограничивают конкретные значение типа и, возможно, предоставляют больше информации о членах таких типов. _Верхнее ограничение типа_ `T <: A` указывает на то что тип `T` относится к подтипу типа `A`.
+Приведем пример, демонстрирующий верхнее ограничение для типа класса `PetContainer`:
+
+```tut
+abstract class Animal {
+ def name: String
+}
+
+abstract class Pet extends Animal {}
+
+class Cat extends Pet {
+ override def name: String = "Cat"
+}
+
+class Dog extends Pet {
+ override def name: String = "Dog"
+}
+
+class Lion extends Animal {
+ override def name: String = "Lion"
+}
+
+class PetContainer[P <: Pet](p: P) {
+ def pet: P = p
+}
+
+val dogContainer = new PetContainer[Dog](new Dog)
+val catContainer = new PetContainer[Cat](new Cat)
+```
+
+```tut:fail
+// это не скомпилируется
+val lionContainer = new PetContainer[Lion](new Lion)
+```
+Класс `PetContainer` принимает тип `P`, который должен быть подтипом `Pet`. `Dog` и `Cat` - это подтипы `Pet`, поэтому мы можем создать новые `PetContainer[Dog]` и `PetContainer[Cat]`. Однако, если мы попытаемся создать `PetContainer[Lion]`, то получим следующую ошибку:
+
+`type arguments [Lion] do not conform to class PetContainer's type parameter bounds [P <: Pet]`
+
+Это потому, что `Lion` не является подтипом `Pet`.
diff --git a/_ru/tour/variances.md b/_ru/tour/variances.md
new file mode 100644
index 0000000000..4b3a1d4a3f
--- /dev/null
+++ b/_ru/tour/variances.md
@@ -0,0 +1,154 @@
+---
+layout: tour
+title: Вариантность
+
+discourse: true
+
+partof: scala-tour
+
+num: 19
+language: ru
+next-page: upper-type-bounds
+previous-page: generic-classes
+
+---
+
+Вариантность (Variances) - это указание определенной специфики взаимосвязи между связанными типам. Scala поддерживает вариантную аннотацию типов у [обобщенных классов](generic-classes.html), что позволяет им быть ковариантными, контрвариантными или инвариантными (если нет никакого указание на вариантность). Использование вариантности в системе типов позволяет устанавливать понятные взаимосвязи между сложными типами, в то время как отсутствие вариантности может ограничить повторное использование абстракции класса.
+
+```tut
+class Foo[+A] // ковариантный класс
+class Bar[-A] // контрвариантный класс
+class Baz[A] // инвариантными класс
+```
+
+### Ковариантность
+
+Параметр типа `A` обобщенного класса можно сделать ковариантным с помощью аннотации `+A`. Для некоторого класса `List[+A]`, указание `A` в виде коварианта подразумевает, что для двух типов `A` и `B`, где `A` является подтипом `B`, `List[A]` представляет собой подтип `List[B]`. Что позволяет нам создавать очень полезные и интуитивно понятные взаимоотношения между типами с использованием обобщений (generics).
+
+Рассмотрим простую структуру классов:
+
+```tut
+abstract class Animal {
+ def name: String
+}
+case class Cat(name: String) extends Animal
+case class Dog(name: String) extends Animal
+```
+
+И `Cat` (кошка) и `Dog`(собака) являются подтипами `Animal`(животное). Стандартная библиотека Scala имеет обобщенный неизменяемый тип `List[+A]`, где параметр типа `A` является ковариантным. Это означает, что `List[Cat]` - это `List[Animal]`, а `List[Dog]` - это также `List[Animal]`. Интуитивно понятно, что список кошек и список собак - это список животных и вы должны быть в состоянии заменить любого из них на `List[Animal]`.
+
+В следующем примере метод `printAnimalNames` принимает в качестве аргумента список животных и выводит их имена в новой строке. Если бы `List[A]` не был ковариантным, последние два вызова метода не компилировались бы, что сильно ограничило бы полезность метода `printAnimalNames`.
+
+```tut
+object CovarianceTest extends App {
+ def printAnimalNames(animals: List[Animal]): Unit = {
+ animals.foreach { animal =>
+ println(animal.name)
+ }
+ }
+
+ val cats: List[Cat] = List(Cat("Whiskers"), Cat("Tom"))
+ val dogs: List[Dog] = List(Dog("Fido"), Dog("Rex"))
+
+ printAnimalNames(cats)
+ // Whiskers
+ // Tom
+
+ printAnimalNames(dogs)
+ // Fido
+ // Rex
+}
+```
+
+### Контрвариантность
+
+Параметр типа `A` обобщенного класса можно сделать контрвариантным с помощью аннотации `-A`. Это создает схожее, но противоположное ковариантным, взаимоотношения между типом параметра и подтипами класса. То есть, для некого класса `Writer[-A]`, указание `A` контрвариантным подразумевает, что для двух типов `A` и `B` где `A` является подтипом `B`, `Writer[B]` является подтипом `Writer[A]`.
+
+Рассмотрим классы `Cat`, `Dog`, и `Animal`, описанные выше для следующего примера:
+
+```tut
+abstract class Printer[-A] {
+ def print(value: A): Unit
+}
+```
+
+`Printer[A]` - это простой класс, который знает, как распечатать некоторый тип `A`. Давайте определим подклассы для конкретных типов:
+
+```tut
+class AnimalPrinter extends Printer[Animal] {
+ def print(animal: Animal): Unit =
+ println("The animal's name is: " + animal.name)
+}
+
+class CatPrinter extends Printer[Cat] {
+ def print(cat: Cat): Unit =
+ println("The cat's name is: " + cat.name)
+}
+```
+
+Если `Printer[Cat]` знает, как распечатать любой класс `Cat` в консоли, а `Printer[Animal]` знает, как распечатать любое `Animal` в консоли, то разумно если `Printer[Animal]` также знает, как распечатать любое `Cat`. Обратного отношения нет, потому что `Printer[Cat]` не знает, как распечатать любой `Animal` в консоли. Чтоб иметь возможность заменить `Printer[Animal]` на `Printer[Cat]`, необходимо `Printer[A]` сделать контрвариантным.
+
+```tut
+object ContravarianceTest extends App {
+ val myCat: Cat = Cat("Boots")
+
+ def printMyCat(printer: Printer[Cat]): Unit = {
+ printer.print(myCat)
+ }
+
+ val catPrinter: Printer[Cat] = new CatPrinter
+ val animalPrinter: Printer[Animal] = new AnimalPrinter
+
+ printMyCat(catPrinter)
+ printMyCat(animalPrinter)
+}
+```
+
+Результатом работы этой программы будет:
+
+```
+The cat's name is: Boots
+The animal's name is: Boots
+```
+
+### Инвариантность
+
+Обобщенные классы в Scala по умолчанию являются инвариантными. Это означает, что они не являются ни ковариантными, ни контрвариантными друг другу. В контексте следующего примера класс `Container` является инвариантным. Между `Container[Cat]` и `Container[Animal]`, нет ни прямой, ни обратной взаимосвязи.
+
+```tut
+class Container[A](value: A) {
+ private var _value: A = value
+ def getValue: A = _value
+ def setValue(value: A): Unit = {
+ _value = value
+ }
+}
+```
+
+Может показаться что `Container[Cat]` должен также являться и `Container[Animal]`, но позволить мутабельному обобщенному классу быть ковариантным было бы небезопасно. В данном примере очень важно, чтобы `Container` был инвариантным. Предположим, что `Container` на самом деле был ковариантным, что-то вроде этого могло случиться:
+
+```
+val catContainer: Container[Cat] = new Container(Cat("Felix"))
+val animalContainer: Container[Animal] = catContainer
+animalContainer.setValue(Dog("Spot"))
+val cat: Cat = catContainer.getValue // Ой, мы бы закончили присвоением собаки к коту.
+```
+
+К счастью, компилятор остановит нас прежде, чем мы зайдем так далеко.
+
+### Другие Примеры
+
+Другим примером, который может помочь понять вариантность, является трейт `Function1[-T, +R]` из стандартной библиотеки Scala. `Function1` представляет собой функцию с одним параметром, где первый тип `T` представляет собой параметр типа, а второй тип `R` представляет собой тип результата. Функция `Function1` является контрвариантной в рамках типа принимаемого аргумента, а ковариантной - в рамках возвращаемого типа. Для этого примера мы будем использовать явное обозначение типа `A =>B` чтоб продемонстрировать `Function1[A, B]`.
+
+Рассмотрим схожий пример `Cat`, `Dog`, `Animal` в той же взаимосвязи что и раньше, плюс следующее:
+
+```tut
+abstract class SmallAnimal extends Animal
+case class Mouse(name: String) extends SmallAnimal
+```
+
+Предположим, мы работаем с функциями, которые принимают типы животных и возвращают типы еды, которую они едят. Если мы хотим `Cat => SmallAnimal` (потому что кошки едят маленьких животных), но вместо этого мы получим функцию `Animal => Mouse`, то наша программа все равно будет работать. Интуитивно функция `Animal => Mouse` все равно будет принимать `Cat` в качестве аргумента, тк `Cat` является `Animal`, и возвращать `Mouse` - который также является и `SmallAnimal`. Поскольку мы можем безопасно заменить первое вторым, можно сказать, что `Animal => Mouse` аналогично `Cat => SmallAnimal`.
+
+### Сравнение с другими языками
+
+В языках, похожих на Scala, разные способы поддержи вариантности. Например, указания вариантности в Scala очень похожи на то, как это делается в C#, где такие указания добавляются при объявлении абстракции класса (вариантность при объявлении). Однако в Java, указание вариантности задается непосредственно при использовании абстракции класса (вариантность при использовании).