Псевдоним типа Scala с сопутствующим объектом

Я относительно новый пользователь Scala и хотел узнать мнение о текущем дизайне моего кода.

У меня есть несколько классов, которые все представлены как Vector [Byte] фиксированной длины (в конечном итоге они используются в алгоритме обучения, для которого требуется байтовая строка), скажем, A, B и C. Я бы хотел, чтобы эти классы назывались A , B и C в других местах пакета для удобочитаемости, и мне не нужно добавлять какие-либо дополнительные методы класса в Vector для этих методов. Следовательно, я не думаю, что шаблон расширения моей библиотеки здесь полезен. Тем не менее, я хотел бы включить все полезные функциональные методы, которые поставляются с Vector, без необходимости каждый раз «сверлить» объект-оболочку. Поскольку здесь важна эффективность, я также не хотел дополнительного веса обертки.

Поэтому я решил определить псевдонимы типов в объекте пакета:

package object abc {
    type A: Vector[Byte]
    type B: Vector[Byte]
    type C: Vector[Byte]
}

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

package object abc {
    type A: Vector[Byte]
    object A {
        val LENGTH: Int = ...
        def apply(...): A = {
            Vector.tabulate...
        }
    }
    ...
}

Все компилируется, и это позволяет мне делать такие вещи:

val a: A = A(...)
a map {...} mkString(...)

Я не могу найти ничего, специально предупреждающего о написании объектов-компаньонов для псевдонимов типов, но, похоже, это противоречит тому, как следует использовать псевдонимы типов. Это также означает, что все три этих класса определены в одном файле, тогда как в идеале их следует разделить.

  1. Есть ли скрытые проблемы с этим подходом?
  2. Есть ли лучший дизайн для этой проблемы?

Спасибо.


person Whiskee    schedule 29.08.2015    source источник


Ответы (1)


Я думаю, это совершенно нормально, потому что на самом деле вы не реализуете объект-компаньон.

Если бы это было так, у вас был бы доступ к закрытым полям immutable.Vector изнутри object A (например, private var dirty), которого у вас нет.

Таким образом, хотя кажется, что A является сопутствующим объектом, на самом деле это не так.

Если бы было возможно создать объект-компаньон для любого типа с помощью псевдонима типа, это сделало бы ограничения видимости членов спорными (за исключением, может быть, private|protected[this]).

Кроме того, наименование объекта, подобное псевдониму типа, проясняет контекст и назначение объекта, что является плюсом в моей книге.

Иметь их все в одном файле — это то, что довольно часто встречается в scala, насколько я знаю (например, при использовании шаблона класса типов).

Таким образом: Никаких подводных камней, насколько я знаю. И, имхо, нет необходимости в другом подходе.

person Sascha Kolberg    schedule 29.08.2015
comment
Имплициты, определенные в этом объекте (A), НЕ попадают в область действия при работе с параметром типа A. Например, в случае jsonFormat() из spray-json. - person Ákos Vandra; 15.07.2016