Недавно я смутился, как организовать мой код Scala, потому что есть много вариантов.
Существуют ли какие-либо рекомендации для Scala, как/когда использовать пакеты, объекты, объекты пакета для организации кода?
Недавно я смутился, как организовать мой код Scala, потому что есть много вариантов.
Существуют ли какие-либо рекомендации для Scala, как/когда использовать пакеты, объекты, объекты пакета для организации кода?
Во-первых, нам нужно понять возможности и ограничения каждой стратегии модуляции.
Они работают так же, как в Java. Вы можете использовать много файлов для объявления разных частей одного пакета, и вы можете вложить много уровней в глубину. Это обеспечивает максимальную гибкость вашего макета. Однако, поскольку загрузчики классов по умолчанию ожидают, что будут только найти классы и интерфейсы в пакетах, все Scala позволяет вам помещать туда. (Классы, черты и объекты.)
Объекты могут содержать что угодно: методы, поля, другие объекты, классы, черты и т.д. Подклассы, черты и объекты на самом деле являются их собственными отдельными объектами с содержащим объектом как префикс с наименованием (в соответствии с JVM). Объект должен содержаться полностью внутри одного файла, и хотя вы можете вложить подклассы произвольно глубоко, это делается путем извлечения более длинных имен, а не добавления в путь для загрузчика классов.
Проблема с наличием только объектов и пакетов заключается в том, что вам может понадобиться вложенная структура:
scala.xml
scala.xml.include
scala.xml.include.sax
чтобы вам нужно было использовать пакеты (чтобы не иметь один гигантский файл и тревожные имена классов). Но вы также можете захотеть
import scala.xml._
чтобы сделать для вас различные константы и неявные преобразования, чтобы вам нужно было использовать объект. объекты пакета приходят на помощь; они по существу те же, что и обычные объекты, но когда вы говорите
import scala.xml._
вы получаете как все в пакете (scala.xml._
), так и все в соответствующем объекте пакета (scala.xml.package
).
Теперь, когда мы знаем, как работает каждая часть, существуют довольно очевидные правила организации:
object
на package object
в большинстве случаев.Помимо пакетов и объектов есть "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
Я использую пакеты всякий раз, когда могу, то есть когда "модуль" только что сделан из определений классов/признаков/объектов. Пакеты имеют то преимущество, что они напрямую доступны из Java без странного синтаксиса.
Во всех остальных случаях я использую в основном простые объекты.
Иногда у меня есть один объект пакета для каждого проекта в корне пакета проекта. Этот объект пакета сохраняет все необходимые импликации и самый важный класс и объекты. Он позволяет получить хороший однострочный импорт для всего проекта.
Если вы интересуетесь только пространством имен и разбиением кода на отдельные файлы (как это похоже на OP), см. ответ @Rex.
Если вы ожидаете большего от модульной системы, такой как взаимозаменяемость или стандартные функции ML-стиля, вы можете использовать описанный ниже здесь.
В принципе, интерфейсы модулей (так называемые подписи в SML) становятся чертами в Scala. Модули (aka structure) - это объекты в Scala. Функторы могут быть переведены на классы, абстрактные классы или даже на некоторые черты с некоторой реализацией с аргументами-функторами, преобразованными в абстрактные поля или аргументы конструктора, в зависимости от того, хотите ли вы, чтобы результирующие модули имели совместимые типы или нет.