Alan Coromano
Alan Coromano

Reputation: 26008

Scala's naming convention for traits

Suppose I have a trait in Scala

trait Connection {

  def init(name: String)
  def dispose
}

And I want to create a class which implements it. But I want to name it as Connection also:

class Connection extends Connection {
  // ....
 }

It's not going to work. Of course, I could name trait something differently, but it turned out that the naming convention in Scala says that I should name trait as ordinary classes, meaning without any prefix, which I would use in C# (IConnection where IConnection would be the interface).

And in this particular case the name of Connection for the class and the trait is more suitable.

Or did I miss something in Scala's naming convention?

Upvotes: 28

Views: 11634

Answers (4)

It's not a convention but something used in the scala.collection is the suffix Like used in traits:

  • SeqLike: A template trait for sequences of type Seq[A].
  • MapLike: A template trait for maps, which associate keys with values.

And so on.

I guess it's their way to say Rectangle/Rectangular where this relation (Seq/SeqLike) does not have a clear naming.

Upvotes: 11

OlliP
OlliP

Reputation: 1585

In Martin Odersky's book there is a sample with a class Rectangle that extends a trait Rectangular and a class Rational that extends a trait Ordered. So the pattern seems here to be to use an adjective for the trait name an a subject for the class name. So in your case it would be "class Connection extends Connected". At least I like this more than "class ConnectionImpl extends Connection".

Upvotes: 8

Nikita Volkov
Nikita Volkov

Reputation: 43309

The fact that you are extracting a general API into a Connection trait itself implies that it'll have multiple specific implementations. Those implementations will of course be related to some more specific entities, e.g. a MySQL or an H2 database.

There are several approaches to your problem depending on the chosen architecture of your app:

  1. If you keep the specific implementations in the same namespace you get:

    • myApp.Connection

    • myApp.MySqlConnection

    • myApp.H2Connection

  2. But the above is actually discouraged due to redundancy in names (the *Connection part) and introduction of a new package is recommended, e.g.:

    • myApp.Connection

    • myApp.connections.MySql

    • myApp.connections.H2

    or

    • myApp.Connection

    • myApp.Connection.MySql

    • myApp.Connection.H2

    if you choose to place the specific implemntation in a companion object of Connection.

  3. In more advanced approaches to architecture you will end up with specific implementations having private packages:

    • myApp.Connection

    • myApp.mySql.Connection

    • myApp.h2.Connection

    And even here although you have the Connection name clashing it's easily solvable due to types being located in different packages by using qualified references (myApp.Connection) or qualified imports:

    import myApp.{Connection => GeneralConnection} //or IConnection if you insist
    

Upvotes: 18

om-nom-nom
om-nom-nom

Reputation: 62835

The common practice for naming class that implements some interface/trait is to add Impl as postfix (and don't add any prefixes/postfixes to interface/trait):

class ConnectionImpl extends Connection {
  // ....
}

Why? Because in good code you write functions against interfaces, so you wont polute your functions with thoose I's:

def sendThings(conn: Connection) {


}

versus

def sendThings(conn: IConnection) {


}

If you have multiple implementations, this, of course should be Connection trait, HttpConnection class1, JdbcConnection class2.

Upvotes: 5

Related Questions