隐式参数和重载问题

时间:2012-10-05 18:17:49

标签: scala overloading implicit

trait DAOContract[T <: Entity] {
  // default create
  def create(t: T): Option[Int]
}

trait UserContract extends DAOContract[User] {
  // provide alternate create method for transactional blocks
  def create(u: User)(implicit ss: Session): Either[String, Int]
  ...
}

// DAO provides create implementation with embedded session
class UserDAO(implicit val db: Connection) 
  extends DAO[User] with UserContract {

  import db.Driver.Implicit._
  import org.scalaquery.ql._
  ...
}

在控制器中

dao.create(model) // boom, no implicit session

我希望我在这里遗漏了一些东西:为什么scala编译器无法区分上面的2个create方法签名?

基本上,如果不为事务性操作(即返回Either)或独立操作提出不同的方法命名约定,我就无法重载DAO操作。

或者,我只是以错误的方式处理事情,完全可能......

2 个答案:

答案 0 :(得分:1)

Scala禁止这样做有原因:

  1. 想象一下,您的create方法将是:

    def create(t: User): Function[Int,Something]
    def create(u: User)(implicit ss: Session): Either[String, Int]
    

    然后调用create(x)(y)将适用于他们两个。

  2. 即使(1.)中的问题可以通过Scala编译器仔细检查函数的类型来解决,也很容易出错。在这样的设置中,程序员很容易犯错误。强制函数使用不同的名称可确保程序员始终知道他们所称的内容。


  3. 如果将方法更改为具有相同的返回类型,并且如果您愿意冒险,可以尝试这样的事情:

    trait Broken {
      final def foo(x: Int)(implicit session: String = null): Option[Int] =
        if (session == null) foo1(x)
        else foo2(x, session);
    
      def foo1(x: Int): Option[Int]
      def foo2(x: Int, session: String): Option[Int]
    }
    class Example extends Broken {
      def foo2(x: Int, y: String) = Some(2)
      def foo1(x: Int) = Some(1)
    }
    
    object Test extends App {
      def withImplicit(e: Example) = {
        implicit val imp = "hey"
        e.foo(1) // (imp)
      }
      def withoutImplicit(e: Example) = e.foo(1)
    
      println(withImplicit(new Example()));
      println(withoutImplicit(new Example()));
    }
    

    当隐含值可用时,将调用相应的方法。否则,调用没有“session”参数的方法。但我强烈阻止这种做法。只是一个小错误会导致调用错误的变体,这将很难调试。

答案 1 :(得分:0)

您的创建方法有不同的sigs。一个返回一个Either,另一个返回一个Option。加上隐含的。您可能需要隐式使用并从两个

返回Option [Int]