Какой правильный способ сделать это в Scala - PullRequest
0 голосов
/ 16 марта 2011

Итак, мне нужно параллельные структуры классов, Books и Makers.Создатель создает книгу на основе какого-то файла или чего-то еще.Мы можем упростить определение базового Создателя до:

class Maker {
  type PF = (String, Book) => Book
  def apply(in: Source): Book = {
    mkMap(in, parseTop)
  }
  def mkMap(in: Source, top: PF) {
    var res = new Book
    in.getLines.foreach { ln => res = top(ln, res)
  }
  def parseTop(line: String, book: Book): Book = {
    // really makes a new Book object with changes based on the content of `line` and returns it
    book
  }
}

, и Book выглядит примерно так (не case class, потому что мы хотим иметь возможность наследовать его)

class Book(val title: String = "Untitled", val author: String = "No Author", val language: String = "English")
  def copy(title: String = this.title, author: String = this.author, language: String = this.language) = new Book(title, author, language)

Теперь я хотел бы расширить это, чтобы получить SpecialMaker, который равен SpecialBooks.Специальная книга может быть определена следующим образом:

class SpecialBook(title: String = "Untitled", author: String = "No Author", language: String = "English", val specialness: Int = 9000) extends Book(title, author, language)
  def copy(title: String = this.title, author: String = this.author, language: String = this.language, specialness: Int = this.specialness) = new SpecialBook(title, author, language, specialness)

Единственное, что изменяется при создании SpecialBook из Book, - это то, что функция parseTop выполняет некоторые дополнительные вычисления, чтобы сделать коэффициент особенностискажем так:

class SpecialMaker {
   override def parseTop(line: String, book: SpecialBook): SpecialBook = {
     book.copy(specialness = book.specialness + 9000)
   }
}

Очевидно, что этот код не работает, потому что этот parseTop в конечном итоге назначит SpecialBook книге, среди других проблем.Какой лучший способ решить проблему в Scala?Неявные преобразования?(Может ли что-то делать с параметрами типа работы?)

Если есть шаблон проектирования, который имеет дело с этим, пожалуйста, дайте мне знать, как он называется.

1 Ответ

0 голосов
/ 16 марта 2011

Мой подход, поэтому вы определяете тип возвращаемого значения parseTop путем параметризации типа Maker:

trait Maker[B <: Book] {
  def parseTop(line: String, book: B): B
}
trait Book {
  val title: String
  val author: String
  val language: String
}

case class NonSpecialBook(title: String = "Untitled", author: String = "No Author", language: String = "English") extends Book

case class SpecialBook(title: String = "Untitled", author: String = "No Author", language: String = "English", val specialness: Int = 9000) extends Book

class NonSpecialMaker extends Maker[NonSpecialBook] {
  def parseTop(line: String, book: NonSpecialBook): NonSpecialBook = {
    book
  }
}

class SpecialMaker extends Maker[SpecialBook] {
  def parseTop(line: String, book: SpecialBook): SpecialBook = {
    book.copy(specialness = book.specialness + 9000)
  }
}

Вам нужен метод parseTop в SpecialMaker для обработки SpecialBooks ´s или делает книги особенными? Возможно ли иметь черту для книг, и все типы книг наследуются от этой черты?
Скажите, чего не хватает, чтобы удовлетворить ваши потребности.

РЕДАКТИРОВАТЬ: (из-за комментария)

Вы можете предоставить неявный BookBuilder:

trait Maker[B <: Book] {
  type PF = (String, B) => B
  def parseTop(line: String, book: B): B
  def mkMap(in: Source, top: PF)(implicit bookBuilder: {def apply(): B} ) {
    var res = bookBuilder()  
    // ...
  }
}

Но этот неявный BookBuilder должен неявно находиться в области (или передаваться вручную) каждый раз, когда вы используете mkMap. Я не знаю, когда вы используете mkMap.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...