2
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 个创建方法签名?

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

或者,我只是以错误的方式做事,完全有可能......

4

2 回答 2

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 编译器仔细检查函数的类型来解决,但它很容易出错。在这样的设置中,程序员很容易出错。为函数强制使用不同的名称可确保程序员始终知道他们调用的是什么。


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

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()));
}

当一个隐式值可用时,调用相应的方法。否则,调用没有“会话”参数的方法。但我强烈反对这种方法。一个轻微的错误就会导致调用错误的变体,这将很难调试。

于 2012-10-06T10:45:30.583 回答
0

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

于 2012-10-06T01:08:33.097 回答