Scala内部案例类在子类参数编译错误中

时间:2012-06-20 16:33:08

标签: scala lift html-email

我想设置来自String的Html电子邮件的主体,而不是为升级邮件程序设置Xml节点,所以我将Mailer子类化并重新定义buildMailBody方法:

class HtmlMailer extends Mailer {
  final case class HtmlMailBodyType(text: String) extends MailBodyType

  override protected def buildMailBody(tab: MailBodyType) = {
    tab match {
      case HtmlMailBodyType(text) =>
        val bp = new MimeBodyPart
        bp.setText(text, charSet, "html")
        bp
      case _ => super.buildMailBody(tab)
    }
  }
}

object HtmlMailer extends HtmlMailer

当我尝试使用它时:

import net.liftweb.util.Mailer
import Mailer._    

HtmlMailer.sendMail(From(sender.email), Subject(subject), To(user.email), HtmlMailBodyType(body))

我收到编译错误:

error: type mismatch;
found   : net.liftweb.util.Mailer.From
required: com.mypackage.HtmlMailer.From
Error occurred in an application involving default arguments.
HtmlMailer.sendMail(From(sender.email), Subject(subject), To(user.email), HtmlMailBodyType(body))

为什么会发生这种情况?如何正确修复?

我更改了导入Mailer._以导入HtmlMailer._并且它有效,但我相信它打破了Liskov替换原则,因为我无法替换HtmlMailer而不是Mailer,因为它们具有不同的参数类型?

1 个答案:

答案 0 :(得分:1)

您遇到路径依赖类型和单身人士的问题。当您有嵌套类时,外部类的每个实例都有一个不同的嵌套类实例。

现在,From(加SubjectTo等),因为它们是嵌套的,属于特定实例。在这种情况下,您有两个实例提供它们。它们是对象

net.liftweb.util.Mailer
com.mypackage.HtmlMailer

请注意,这些不是,它们是对象

现在,方法sendMail要求其参数由属于与其自身相同的实例的类组成。提出这样的要求有很多原因,因为有些方法可以做到这一点。

所以,实际上,这里没有违反liskov替换原则,只是违反了导入隐藏的类型。如果你明确地写出来,那就更清楚了:

val myInst: net.liftweb.util.Mailer = HtmlMailer
myInst.sendMail(myInst.From(sender.email), myInst.Subject(subject), myInst.To(user.email), myInst.HtmlMailBodyType(body))

您可以使用HtmlMailernet.liftweb.util.Mailer的任何其他实例替换net.liftweb.util.Mailer,这样就可以了。你不能使用net.liftweb.util.Mailer的两个不同实例,即使它们都属于同一类。