Как смешать явно несовместимые парадигмы: ООП и ФП? [закрытый]

прочитав часть моего кода Scala, я заметил, что он либо функциональный, либо объектно-ориентированный.

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

одно из решений, которое я исследую, - заставить все методы вернуть клон текущего экземпляра с соответствующими изменениями состояния. Кажется, хотят, но может помочь, когда я решу paralelize код, верно ?

каковы наилучшие методы смешивания этих 2 парадигм ? Каков баланс ?

спасибо.

4 ответов


Я думаю, что на самом деле я не согласен с тем, как вы это формулируете:

Я бы не сказал, что мутационные операции над полями объектов являются основной "предпосылкой OO.- Вовсе нет (хотя, наоборот, я!--9-->do думаю, что неизменность является основной предпосылкой FP). Для меня OO-это способ думать о программе модульность больше всего на свете.

теперь, на менее теоретическом и большем уровне гаек и болтов... Скажем, у вас есть что-то вроде:

class Foo(val a : A, val b : B, val c : C) {
  def setB(newb : B) : Foo = new Foo(a, newb, c)
}

... так что вы можете сказать newFoo = foo.setB(b) Как вы предложили в исходном посте. Я бы сказал, что это совершенно прекрасный стиль, и не вызывает беспокойства (о производительности или читаемости или что-то еще). Вы см. много этого с неизменяемыми классами коллекции в библиотеке Scala.


неизменяемые классы-очень хороший способ объединить OO и FP. Скала Библиотеки является отличным примером смешивания OO, неизменяемых объектов и функционального программирования.

в вашем собственном коде Scala классы case действительно помогают реализовать неизменяемый объект, так как у них есть copy метод, который можно использовать в качестве замены шаблона builder.

// begin cheesy example
case class Circle(center: (Double, Double), radius: Double) {
  def move(c: (Double, Double)) = copy(center = c)
  def resize(r: Double) = copy(radius = r)
  def area = math.Pi * radius * radius
}

вы также можете воспользоваться просмотром переговоров Рича Хикки постоянные структуры данных и управляемые ссылки и Мы Еще Там? Оба прекрасно объясняют необходимость неизменности и то, как она помогает нам рассуждать о состоянии. Он говорит обо всем, что касается Clojure, но его точки зрения одинаково хорошо относятся к Scala.


возможно, вы захотите проверить функциональное программирование глава программирования Scala (это доступны бесплатно онлайн), чтобы получить некоторые подсказки.

FP дело не только в резьбе. Функции высокого порядка могут помочь вам очистить и высушить ваш код, делая его более элегантным.


сделать все методы возвращают клон текущего экземпляра

Если вы проверите, как jQuery это делает, он использует метод, называемый цепочкой методов каждый метод, который в противном случае вернул бы void, возвращает $this, поэтому вы можете продолжать вызывать методы один над другим. Вот почему в jQuery предметности, не нарушает традиционных процедурных пользовательского кода в JavaScript.