Несоответствие типов со значениями Scala - PullRequest
2 голосов
/ 21 апреля 2019

Я пытаюсь использовать импликации в Scala.

object TypeClasses extends App {
  trait HTMLWritable {
    def toHTML: String
  }

  case class User(name: String, age: Int, email: String) extends HTMLWritable {
    override def toHTML: String = s"<div>$name ($age yo) <a href=$email/> </div>"
  }

  val john = User("John", 32, "john@rockthejvm.com")
  trait HTMLSerializer[T] {
    def serialize(value: T): String
  }

  object UserSerializer extends HTMLSerializer[User] {
    def serialize(user: User): String = s"<div>${user.name} (${user.age} yo) <a href=${user.email}/> </div>"
  }

  implicit class HTMLEnrichment[T](value: T) {
    def toHTML(serializer: HTMLSerializer[T]): String = serializer.serialize(value)
  }

  println(john.toHTML(UserSerializer))
}

этот код не будет компилироваться:

Error:(41, 23) type mismatch;
 found   : lectures.part4implicits.TypeClasses.UserSerializer.type
 required: Int
  println(john.toHTML(UserSerializer))

У меня проблемы с пониманием сообщения, потому что согласноIntelliJ, john.toHTML - это вызов метода toHTML в классе HTMLEnrichment, который ожидает HTMLSerializer, что я и дал.Нигде я не определил метод toHTML, который требует Int.

1 Ответ

4 голосов
/ 22 апреля 2019

Это потому, что вы случайно перегрузили метод toHTML.Ошибка, которую вы получаете, заключается в том, что String.apply возвращает символ с заданным индексом, поэтому вы получаете эту ошибку о Int.

. Intelij не всегда эффективен при выделении такого родазатенение.Это хорошая идея, чтобы неявные механизмы не включались в модель предметной области, например, разделять специализированные сериализации на имплициты, как вы это делаете:

  implicit object UserSerializer extends HTMLSerializer[User] {
    def serialize(user: User): String = s"<div>${user.name} (${user.age} yo) <a href=${user.email}/> </div>"
  }

Затем удалите все из вашего user и, возможно, добавьтепомощник.

trait HTMLSerializer {
  def toHTML: String
}

object HTMLSerializer {
  // if you put this here you don't need to explicitly import it.
  implicit class HTMLEnrichment[T](val value: T) extends AnyVal {
    def toHTML(implicit serializer: HTMLSerializer[T]): String = 
      serializer.serialize(value)
  }
}

Это означает, что вы можете просто получить тот же эффект, что и метод-компаньон, но вы можете сохранить все красиво отделенным, и вы не рискуете получить такие эффекты затенения.

...