Как смешать явно несовместимые парадигмы: ООП и ФП? [закрытый]
прочитав часть моего кода 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.