Scala ключевое слово типа: как лучше всего использовать его в нескольких классах

Возвращаясь к Scala после написания заклинания Haskell, я начал использовать ключевое слово типа, чтобы сделать мои определения классов более читабельными, например:

type RestfulParams = Map[String, String]
def canonicalize(params: RestfulParams): String = { ... }

Проблема, с которой я столкнулся, заключается в том, что эти определения типов должны жить внутри класса или объекта - они не являются "гражданами первого класса", как в Haskell. Если я попытаюсь определить тип вне класса или объекта, я получаю компилятор expected class or object definition.

Моя проблема заключается в том, как использовать эти типы для нескольких классов и объектов в пакете? То, что я сделал сейчас, кажется довольно уродливым:

object RestfulTypes { type RestfulParams = Map[String, String] etc }

И затем в другом файле класса:

import utils.{RestfulTypes => RT}
def get(resource: String, params: RT.RestfulParams): String = { ... }

Есть ли лучший способ сделать это - и, кстати, гуру Scala считают, что это хорошо или плохо, что типы могут быть определены только внутри классов/объектов?

Ответ 1

Работает ли объекты пакета?

Из статьи:

До 2,8 единственные вещи, которые вы могли бы разместить в пакете, - это классы, черты и автономные объекты. Это, безусловно, наиболее распространенные определения, которые размещаются на верхнем уровне пакета, но Scala 2.8 не ограничивает вас только этими. Любое определение, которое вы можете ввести внутри класса, вы также можете установить на верхний уровень пакета. Если у вас есть вспомогательный метод, который вы хотели бы использовать для целого пакета, перейдите к нему и поместите его прямо на верхний уровень пакета. Для этого вы помещаете определения в объект пакета. Каждому пакету разрешено иметь один объект пакета. Любые определения, помещенные в объект пакета, считаются членами самого пакета.

объект пакета scala уже имеет много типов и значений, поэтому я думаю, что вы можете использовать тот же метод для своих собственных типов.

Ответ 2

Я не уверен, что составляет в этом случае приятность, но вот два варианта:

Использование признака: (Scala Самоотверженный шаблон шаблона)

trait RestfulTypes {
  type Params = Map[String,String]
  //...
}

object MyRestService extends RestService with RestfulTypes { /* ... */ }

Или просто импортируйте элементы объекта, эффективно используя его как пакет:

import util.RestfulTypes._

Ответ 3

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

Пример:

//package myType
package object myType {type mine = List[String]}

Обратите внимание, что объект пакета имеет то же имя, что и пакет, для использования без префикса объекта i.e myType.mine Если вы называете это другим именем, например:

//package myType
package object mainType {type mine = List[String]}

он может быть доступен с помощью mainType.mine при импорте пакета

для получения дополнительной информации: http://www.scala-lang.org/docu/files/packageobjects/packageobjects.html