简体   繁体   English

Scala的特征命名约定

[英]Scala's naming convention for traits

Suppose I have a trait in Scala 假设我在Scala中有一个trait

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: 但是我想把它命名为Connection也是:

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 ). 当然,我可以用不同的方式命名trait ,但事实证明Scala中的命名约定说我应该将trait命名为普通类,这意味着没有任何前缀,我将在C#中使用( IConnectionIConnection作为interface ) 。

And in this particular case the name of Connection for the class and the trait is more suitable. 在这种特殊情况下, classtraitConnection名称更合适。

Or did I miss something in Scala's naming convention? 或者我在Scala的命名约定中遗漏了什么?

The fact that you are extracting a general API into a Connection trait itself implies that it'll have multiple specific implementations. 您将一般API提取到Connection trait本身的事实意味着它将具有多个特定实现。 Those implementations will of course be related to some more specific entities, eg a MySQL or an H2 database. 这些实现当然将与一些更具体的实体相关,例如MySQL或H2数据库。

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, eg: 但实际上由于名称冗余( *Connection部分)而不鼓励使用以上内容,建议引入新包,例如:

    • 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 . 如果您选择将特定实现放在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: 即使在这里,虽然你有Connection名称冲突,但由于类型通过使用限定引用( myApp.Connection )或限定导入而位于不同的包中,因此它很容易解决:

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

It's not a convention but something used in the scala.collection is the suffix Like used in traits: 它不是一个约定,但scala.collection中使用的东西是后缀类似于traits:

  • SeqLike : A template trait for sequences of type Seq[A]. SeqLike :Seq [A]类型序列的模板特征。
  • MapLike : A template trait for maps, which associate keys with values. MapLike :地图的模板特征,它将键与值相关联。

And so on. 等等。

I guess it's their way to say Rectangle/Rectangular where this relation (Seq/SeqLike) does not have a clear naming. 我想这是他们说矩形/矩形的方式,这种关系(Seq / SeqLike)没有明确的命名。

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. 在Martin Odersky的书中,有一个带有Rectangle类的示例,它扩展了一个特性Rectangular和一个扩展特性Ordered的类Rational。 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". 至少我喜欢这个,而不是“类ConnectionImpl扩展连接”。

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): 实现某些接口/特性的命名类的常见做法是将Impl添加为后缀(并且不要向接口/特征添加任何前缀/后缀):

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. 如果你有多个实现,这当然应该是Connection trait, HttpConnection class1, JdbcConnection class2。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM