Практика 1.2 Упражнения по scala.
- Совет
-
-
Прочитайте:
-
Главу основы scala
-
Главу структуры управления
-
Ответ на задание необходимо предоставить в виде файлов Scala и XML, которые были изменены в текущем уроке (для написанного программного кода). Скриншоты интерфейса приложения для заданий выполняемых в интерфейсе и для демонстрации работы кода в системе Global ERP следует отправить в формате PDF, PNG или JPG. Для удобства рекомендуется прислать все файлы в одном архиве.
В ответе на задание должны содержаться элементы, обеспечивающие работоспособность описанного в задании функционала.
Создание класса с тестами
- Перейдите в окно проекта
- Выберете целевой модуль
-
Перейдите в папку с исходными кодами
[module_name]/src/test/scala
- Совет
-
- Создать недостающую папку можно из контекстного меню в idea
New > Directory
-
Создайте пакет
ru.bitec.app.[module_name]
class Lesson1Test extends LangFunSuite{ test("HelloWorld"){ println("hello world") } }
- Совет
-
- Запустить тест можно из контекстного меню, для этого:
-
- Переведите курсор на декларацию функции
- В контекстном меню выполните операцию „Debug“ Подробнее смотрите выполнение тестов в руководстве idea.
Для дополнительной информации смотрите также библиотеку unit тестирования: scalatest
- Примечание
-
- Существуют два специализированных базовых класса для тестовых случаев:
-
-
LangFunSuite
Используется для тестов которые не нуждаются в контроллерах бизнес логики.
Данные тесты не могут использоватьApi
,Pkg
, и не имеют подключения к базе данных по умолчанию. -
ApiTest
В данном тексте доступен контекст автономной бизнес логики, тестовые случаи могут использоватьApi
,Pkg
объекты. При этом запуск теста становится медленней из за необходимости инициализировать контекст.
-
Объявление null типов
Смотри: Руководство разработчика: языки разработки # scala типы
Пример объявления null типов показан в следующей тестовой функции:
test("NullTypes"){ val nvNumber = "1.3".nn val nvNullNumber = None.nn val nvDate = "21.11.2003 00:00:00".nd val nvNullString = None.nn val nvEmptyString = "".ns assert(nvNullString != nvEmptyString) assert((nvNumber + 1.nn) === "2.3".nn) assert((nvNullNumber + 1.nn).isNull) assert( (nvDate+1.day).asNDate() === "22.11.2003".nd) }
Null типы являются доменным аналогом scala типа опций(Option
), они используются для более компактной записи выражений.
Пример использования null типов и option:
//Null типы val a1 = 1.nn val b1 = None.nn assert( (a1+b1).isNull ) //Option val a2 = Some(1) val b2: Option[Int] = None assert( (for(a<-a2;b<-b2) yield a+b).isEmpty )
- Внимание!
-
-
Метод
assert
не выводит в консоль оповещение в случае успешного выполнения тестового кода! Если есть необходимость увидеть все результаты тестов, корректные и некорректные, результат методаassert
можно вывести в консоль при помощиprintln
.
Работа с коллекциями
- Совет
-
- Для более подробной информации по работе с коллекциями смотрите:
ArrayBuffer
ArrayBuffer
используется тогда, когда нужна изменяемая индексированная последовательность общего назначения. Поскольку ArrayBuffer
индексирован, произвольный доступ к элементам выполняется быстро.
val nums = ArrayBuffer(1, 2, 3) // ArrayBuffer(1, 2, 3) nums += 4 // ArrayBuffer(1, 2, 3, 4) nums ++= List(5, 6)
- Совет
-
- Если есть возможность(добавление идет только в конец) используйте
ArrayBuffer
вместоListBuffer
, так как это экономит оперативную память и процессорное время.
Массив
Массив содержит фиксированный набор элементов, массивы удобно применять в константных последовательностях так как они потребляют минимальное количество оперативной памяти, и обладаю высоким быстродействием при переборе значений.
val numbers = Array(1, 2, 3, 4)
- Совет
-
- Если вы неуверены в том какую коллекцию выбрать используйте массив.
Набор
Наборы не содержат одинаковых элементов.
//Эквивалентно Set(1, 2) val set = Set(1, 1, 2)
Кортеж
Кортеж объединяет простые логические элементы коллекции без использования классов.
//Создание кортежа val ingredient = ("Sugar", 25) //Распаковка кортежа val (name, quantity) = ingredient val ingredients = Array(ingredient) //Распаковка в анонимной функции ingredients.foreach{case (name, quantity) => println(s"$name:$quantity") } //Распаковка из опции ingredients.headOption match { case Some((name3, quantity3))=> case _ => }
Кортежи часто используются при работе с картами для комбинации (key,value)
- Совет
-
- Более подробно смотрите кортежи
Карты
Карты используются для организации структуры позволяющей быстро получить значение по ключу.
val map = Map("foo" -> "bar")
Опция
Опция представляет собой контейнер, который хранит какое-то значение или не хранит ничего совсем.
Опция часто используется как результат работы метода который может ничего не вернуть к примеру:
val numbers = Map("one" -> 1, "two" -> 2) numbers.get("two") match { case Some(v)=> case _ => AppException("Ошибка в коде".ns).raise() }
Комбинаторы
Комбинаторы позволяют выполнять операции преобразования и обхода коллекций. Пример работы с коллекциями:
//Обявление массива номеров val numbers = Array(1.nn, 2.nn, 3.nn, 4.nn) //Преобразования массива номеров в массив строк val strings = numbers.map(_.toString()) // Объявление карты val map = Map("steve" -> 100.nn, "bob" -> 101.nn, "joe" -> 201.nn) // Печать элементов массива strings.foreach{v => println(v) } //Печать элементов карты //Выражение case ( k,v ) преобразовывает входящий кортеж //в переменные k,v map.foreach{case ( k,v )=> println(s"$k:$v") } //Фильтрация номеров val someNumbers = numbers.filter(_ >= 3.nn) //Группировка номеров по 2 элемента в группу val groupedNumbers = numbers.grouped(2).toArray //Поиск номера val num = numbers.find(_ === 2.nn).getOrElse(None.nn) //Сортировка номеров по убыванию val sortedNumbers = numbers.sortBy(_.desc) //Сумирование номеров с лева на право //Первый аргумент задает начальное значение val sum = numbers.foldLeft(0.nn)(_+_) //Преобразование коллекции в строку через запятую и вывод на экран println(sortedNumbers.mkString(","))
Json
Загрузка json в модель:
"""{ "values":[ {"id":1}, {"id":2}, {"id":1}, {"id":3} ] }""".ns.jsonToValue(classOf[Data])
Модель Data
должна быть объявлена внешними классами:
/* *Класс, типизирующий какую либо строку(из базы данных, или массива json) с полем id. *Может быть несколько полей с разными типами. */ class Rows{ var id: NNumber = _ } /* *Класс предоставляющий модель данных. */ class Data{ val values: Array[Rows] = Array.empty })
- Примечание
-
- Модель
Data
необходимо так как коллекции в java не хранят информации о вложенных объектах, соответственно выражениеclassOf[Array[Member]]
не может предоставить достаточной информации для типизированной десериализации.
Создание функции
Создайте функцию прибавляющую 1 час к дате.
Создание класса
Создайте scala класс для хранения данных по членам клуба, назовите атрибуты класса в соответствии с примером на json:
{ "memid":0, "surname":"GUEST", "firstname":"GUEST", "address":"GUEST", "zipcode":0, "telephone":"(000) 000-0000", "recommendedby":null, "joindate":"01.07.2012 00:00:00" }
Загрузка классов из json
Загрузите json в модель скала классов:
{"members":[ {"memid":0,"surname":"GUEST","firstname":"GUEST","address":"GUEST","zipcode":0,"telephone":"(000) 000-0000","recommendedby":null,"joindate":"01.07.2012 00:00:00"}, {"memid":1,"surname":"Smith","firstname":"Darren","address":"8 Bloomsbury Close, Boston","zipcode":4321,"telephone":"555-555-5555","recommendedby":null,"joindate":"02.07.2012 12:02:05"}, {"memid":2,"surname":"Smith","firstname":"Tracy","address":"8 Bloomsbury Close, New York","zipcode":4321,"telephone":"555-555-5555","recommendedby":null,"joindate":"02.07.2012 12:08:23"}, {"memid":3,"surname":"Rownam","firstname":"Tim","address":"23 Highway Way, Boston","zipcode":23423,"telephone":"(844) 693-0723","recommendedby":null,"joindate":"03.07.2012 09:32:15"}, {"memid":4,"surname":"Joplette","firstname":"Janice","address":"20 Crossing Road, New York","zipcode":234,"telephone":"(833) 942-4710","recommendedby":1,"joindate":"03.07.2012 10:25:05"} ]}
Описание модели данных:
-
data
Используется для типизации модели данных-
members
Типизированный массив участников-
Member
Участник
-
-
- Совет
-
- Для участника вы можете использовать класс созданные в предыдущем задании.
Поиск последнего участника
Напишите выражение возвращающее члена клуба который присоединился к клубу последним.
В качестве входных данных используйте результат полученный в задании Загрузка классов из json
Для определение последнего присоединившегося необходимо использовать поле joindate