实现中函数参数的Scala名称并不重要?

时间:2017-06-24 08:39:11

标签: scala

我有两个特点:

trait Repository[T] {
  def insert(obj: T): Task[T]
}

trait RoleRepository extends Repository[Role]

然后我添加了RoleRepository的实现:

class RoleRepositoryImplem(val db: Db) extends RoleRepository {
    def insert(role: Role): Task[Role] = {
      //some implementation here
    }

在我的实施中,我犯了一个错误(正如我所想):我已将参数命名为" role"而不是" obj"。但项目实际编译并运行得很好。它看起来很奇怪我认为如果有人根据特质存储库编写自己的代码,这会导致很多混乱。我在我的项目中使用Scala 2.12.2。有人可以解决这个问题吗?为什么会发生这种情况以及如何解决这个问题?

3 个答案:

答案 0 :(得分:2)

您使用的名称取决于编译时调用时已知的类型,而不是实现的真实名称。

例如:

val repo: RoleRepositoryImplem = new RoleRepositoryImplem(db) 
repo.insert(role = foobar) // this works
val repoAsTrait: Repository[Role] = repo 
repoAsTrait.insert(obj = foobar) // role name no longer works

我发现它确实令人困惑:当您只知道自己有Repository时,则使用更通用的名称obj,否则role如果您知道通话时的准确类型。

旁注:

请记住,当scala编译为字节码时,参数名称将丢失,因为字节码不处理命名参数。因此,在运行时无法知道参数的真实名称是什么(不包括slooooow内省)。 scala编译器只是将名称转换为参数中的位置。

答案 1 :(得分:2)

方法的参数只是它接受的type的名称。

假设您有一个方法addNumber(number: T),当您override方法时,您必须遵循相同的签名,但您可以为参数提供一个更好的名称,这在该上下文中更有意义,例如addNumber(integer: Integer)

Bag为例,其中包含item s(项目是此处的通用术语)

  trait Bag[T] {
    def addToBag(item: T)
    def items(): List[T]
  }

如果包中包含水果,你会向其中添加fruit,因此将输入参数调用为fruit: Fruit会更有意义,但是你可以根据需要调用它。

  case class Fruit(name: String)
  trait FruitBag extends Bag[Fruit]


  class MyFruitBag extends FruitBag {
    var list = scala.collection.mutable.ListBuffer[Fruit]()

    override def addToBag(fruit: Fruit): Unit = {
      println("adding item")
      list.+=:(fruit)
    }

    override def items(): List[Fruit] = list.toList
  }

如果包中包含Toy s,您将需要将输入参数调用为toy,这更具上下文性,但您可以再次为其提供所需的名称。

  case class Toy(name: String)
  trait ToyBag extends Bag[Toy]
  class MyToysBag extends ToyBag {
    var list = scala.collection.mutable.ListBuffer[Toy]()

    override def addToBag(toy: Toy): Unit = {
      println("adding item")
      list.+=:(toy)
    }

    override def items(): List[Toy] = list.toList
  }

摘要是当您覆盖仅override签名的方法时,不一定是参数的确切名称,参数是根据子类的上下文命名的。

答案 2 :(得分:1)

重写/实现的方法参数的名称在超类/特征和子类中不需要相同。在Scala和更多语言中都是如此。在上述情况下,OO语言通常不需要相同的参数名称。