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

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?

4b9b3361

Ответ 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.