Подтвердить что ты не робот

"Модульные" Scala рекомендации

Недавно я смутился, как организовать мой код Scala, потому что есть много вариантов.

Существуют ли какие-либо рекомендации для Scala, как/когда использовать пакеты, объекты, объекты пакета для организации кода?

4b9b3361

Ответ 1

Понимание возможностей Scala

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

Пакеты

Они работают так же, как в Java. Вы можете использовать много файлов для объявления разных частей одного пакета, и вы можете вложить много уровней в глубину. Это обеспечивает максимальную гибкость вашего макета. Однако, поскольку загрузчики классов по умолчанию ожидают, что будут только найти классы и интерфейсы в пакетах, все Scala позволяет вам помещать туда. (Классы, черты и объекты.)

Объекты

Объекты могут содержать что угодно: методы, поля, другие объекты, классы, черты и т.д. Подклассы, черты и объекты на самом деле являются их собственными отдельными объектами с содержащим объектом как префикс с наименованием (в соответствии с JVM). Объект должен содержаться полностью внутри одного файла, и хотя вы можете вложить подклассы произвольно глубоко, это делается путем извлечения более длинных имен, а не добавления в путь для загрузчика классов.

Объекты пакета

Проблема с наличием только объектов и пакетов заключается в том, что вам может понадобиться вложенная структура:

scala.xml
scala.xml.include
scala.xml.include.sax

чтобы вам нужно было использовать пакеты (чтобы не иметь один гигантский файл и тревожные имена классов). Но вы также можете захотеть

import scala.xml._

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

import scala.xml._

вы получаете как все в пакете (scala.xml._), так и все в соответствующем объекте пакета (scala.xml.package).

Как модулировать код

Теперь, когда мы знаем, как работает каждая часть, существуют довольно очевидные правила организации:

  • Поместите связанный код в пакет
  • Если есть много связанных частей, поместите их в подпакеты
  • Если пакет требует implicits или констант, поместите их в объект пакета для этого пакета
  • Если у вас есть ветвь ветки вашей иерархии пакетов, то это ваш выбор в отношении того, должен ли он быть объектом или объектом пакета. Есть несколько вещей, которые не разрешены для объектов пакета (хотя список все меньше уменьшается - я не уверен, что что-то осталось, кроме запрета на затенение других имен в пакете), поэтому обычный объект может быть лучшим выбором. Пока вы не беспокоитесь о совместимости с двоичными файлами, легко изменить свой разум позже - просто измените object на package object в большинстве случаев.

Ответ 2

Помимо пакетов и объектов есть "implicits", которые помогают структурировать ваш код. Хороший ориентир для использования (избегайте злоупотребления) можно найти здесь: http://suereth.blogspot.com/2011/02/slides-for-todays-nescala-talk.html

Я также предлагаю классы типов для структурирования вашего кода. Вот хорошая запись на эту тему: http://debasishg.blogspot.com/2010/07/refactoring-into-scala-type-classes.html

Ответ 3

Я использую пакеты всякий раз, когда могу, то есть когда "модуль" только что сделан из определений классов/признаков/объектов. Пакеты имеют то преимущество, что они напрямую доступны из Java без странного синтаксиса.

Во всех остальных случаях я использую в основном простые объекты.

Иногда у меня есть один объект пакета для каждого проекта в корне пакета проекта. Этот объект пакета сохраняет все необходимые импликации и самый важный класс и объекты. Он позволяет получить хороший однострочный импорт для всего проекта.

Ответ 4

Если вы интересуетесь только пространством имен и разбиением кода на отдельные файлы (как это похоже на OP), см. ответ @Rex.

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

В принципе, интерфейсы модулей (так называемые подписи в SML) становятся чертами в Scala. Модули (aka structure) - это объекты в Scala. Функторы могут быть переведены на классы, абстрактные классы или даже на некоторые черты с некоторой реализацией с аргументами-функторами, преобразованными в абстрактные поля или аргументы конструктора, в зависимости от того, хотите ли вы, чтобы результирующие модули имели совместимые типы или нет.