Scala соглашение об именах для признаков
Предположим, что у меня есть trait
в Scala
trait Connection {
def init(name: String)
def dispose
}
И я хочу создать класс, который его реализует. Но я также хочу называть его Connection
:
class Connection extends Connection {
// ....
}
Это не сработает. Конечно, я мог бы назвать trait
что-то по-другому, но оказалось, что соглашение об именах в Scala говорит, что я должен назвать черту как обычные классы, то есть без какого-либо префикса, который я бы использовал в С# (IConnection
где IConnection
будет interface
).
И в этом конкретном случае более подходящим является название Connection
для class
и trait
.
Или я пропустил что-то в соглашении по именованию Scala?
Ответы
Ответ 1
Тот факт, что вы извлекаете общий API в собственный признак Connection
, подразумевает, что он будет иметь несколько конкретных реализаций. Конечно, эти реализации будут связаны с некоторыми более конкретными объектами, например. базу данных MySQL или H2.
В зависимости от выбранной архитектуры вашего приложения существует несколько подходов к вашей проблеме:
-
Если вы сохраняете конкретные реализации в одном и том же пространстве имен, вы получаете:
-
myApp.Connection
-
myApp.MySqlConnection
-
myApp.H2Connection
-
Но вышеупомянутое действительно обескураживается из-за избыточности в именах (часть *Connection
) и рекомендуется введение нового пакета, например:
-
myApp.Connection
-
myApp.connections.MySql
-
myApp.connections.H2
или
-
myApp.Connection
-
myApp.Connection.MySql
-
myApp.Connection.H2
если вы решите разместить конкретную реализацию в сопутствующем объекте Connection
.
-
В более сложных подходах к архитектуре вы получите конкретные реализации с частными пакетами:
-
myApp.Connection
-
myApp.mySql.Connection
-
myApp.h2.Connection
И даже здесь, хотя вы столкнулись с именем Connection
, оно легко разрешимо из-за того, что типы располагаются в разных пакетах с использованием квалифицированных ссылок (myApp.Connection
) или квалифицированных импортов:
import myApp.{Connection => GeneralConnection} //or IConnection if you insist
Ответ 2
В книге Мартина Одерского есть образец с классом Rectangle, который расширяет черту Rectangular и класс Rational, который расширяет признак Упорядоченный. Таким образом, шаблон, похоже, состоит в том, чтобы использовать прилагательное для имени признака субъекта для имени класса. Поэтому в вашем случае это будет "class Connection extends Connected". По крайней мере, мне нравится это больше, чем "class ConnectionImpl extends Connection".
Ответ 3
Это не соглашение, а что-то, что используется в scala.collection - это суффикс. Как используется в чертах:
- SeqLike: шаблонный шаблон для последовательностей типа Seq [A].
- MapLike: шаблонный шаблон для карт, которые связывают ключи со значениями.
И так далее.
Я предполагаю, что это их способ сказать Rectangle/Rectangular, где это отношение (Seq/SeqLike) не имеет четкого названия.
Ответ 4
Общей практикой для класса именования, реализующего некоторый интерфейс/признак, является добавление Impl в качестве постфикса (и не добавляйте никаких префиксов/постфиксных интерфейсов/признаков):
class ConnectionImpl extends Connection {
// ....
}
Почему? Потому что в хорошем коде вы записываете функции против интерфейсов, поэтому вы не будете публиковать свои функции с помощью thoose I:
def sendThings(conn: Connection) {
}
против
def sendThings(conn: IConnection) {
}
Если у вас несколько реализаций, это, конечно, должно быть Connection
trait, HttpConnection
class1, JdbcConnection
class2.