Сначала позвольте мне сказать вам, что я полностью понимаю ваши чувства, я должен был пройти через ту же самую ситуацию.И позвольте мне также сказать вам, что изучение Clojure (функциональное программирование) того стоило (конечно, это личная оценка).
У Clojure есть инструменты ООП, например, у вас есть defrecord
и defprotocol
.Но в своей основе он более функциональный, чем объектно-ориентированный, и вы ощутите его реальную выгоду, только если начнете мыслить функционально и неизменность .
Чтобы написать идиоматическую Clojure, вам необходимо переключитьсяваше мышление от объектов к функциям.На функциональном языке все вращается вокруг функций, а не данных (объектов).Данные представлены с использованием тривиальных структур данных, таких как карты.Вы не связываете функции с их данными, как в ООП.В вашем случае вместо класса Savings Account
и класса Pension
вам просто нужна структура данных для представления этих данных, например карта:
(def saving-account {:balance 0.0, :interest-rate 0.0})
(def pension {:annual-income 0.0, :annual-increase 0.0})
Метод Withdraw
будет простобыть функцией для каждого случая, например:
(defn withdraw-from-saving-account [sa amount] ( <return updated saving account map> ))
(defn withdraw-from-pension [p] ( <return updated pension map> ))
В Clojure вы обычно хотите сохранить все неизменяемым, поэтому вышеприведенные функции возвращают новую обновленную карту и не изменяют никакого существующего состояния в существующих картах.Это дает некоторое время, чтобы привыкнуть к парадигме изменчивого состояния, такой как ООП Java.Идиоматическая Clojure (как и большинство функциональных языков программирования) в значительной степени основана на композиции функций (которая подразумевает короткие функции одной задачи, когда это возможно) и очень ограниченном использовании переменных.Если вы когда-либо использовали оболочку * nix, это очень похоже на команду piping / chaining.
Обратите внимание, что вы также можете упростить вышеуказанные функции, объявив один Withdraw
multimethod .И если вы предпочитаете, вы также можете использовать типы данных для более точного определения данных и использовать протоколы для реализации интерфейса для этих записей, что ближе к тому, что вы делаете в Java.Главное, что вам нужно понять, это то, что, хотя Java вращается вокруг классов, Clojure вращается вокруг функций и неизменяемых данных, и чем больше pure функция, тем лучше.