статические методы делают Java псевдофункциональным языком?
Я думал о сообщении Миско Хевери о том, что статические методы в Java убивают тестируемость . Я хочу обсуждать не проблему тестируемости, а концепцию статических методов. Почему люди так его ненавидят?
Это правда, что у нас нет замыканий (но у нас есть немного неудобные анонимные функции), лямбды и функции как объекты первого класса. В некотором смысле, я думаю, что статические методы можно использовать для имитации функций как объектов первого класса.
Ответов (6)6
Одна из характеристик функционального программирования - неизменность данных. static
подразумевает, что вам не нужен объект (экземпляр), представляющий состояние, так что это неплохое начало. Однако у вас есть состояние на уровне класса, но вы можете это сделать final
. Поскольку (статические) методы вообще не являются функциями первого класса, вам все равно понадобятся уродливые конструкции, такие как анонимные классы, чтобы приблизиться к определенному стилю функционального программирования в Java.
FP лучше всего делать на функциональном языке, поскольку он имеет необходимую языковую поддержку для таких вещей, как функции высшего порядка, неизменяемость, ссылочная прозрачность и так далее.
Однако это не означает, что вы не можете программировать в функциональном стиле на императивном языке, таком как Java. Можно привести и другие примеры. Вы делаете ООП не потому, что программируете на Java. Вы можете программировать с глобальными данными и неструктурированными потоками управления ( goto
) на структурированном языке C++. Я могу выполнять ООП на таком функциональном языке, как Scheme. И т.п.
Макконнелл отмечает разницу программирования на языке по сравнению с программированием на языке в полный код (также очень популярный ссылка на SO).
Короче говоря, если вы скажете, что «статические методы имитируют функции первого класса», я не согласен.
Если бы, однако, а я думаю, что это было больше тем, что вы пытались донести, вы бы сказали, что «статические методы могут помочь при программировании в функциональном стиле на Java», я согласен.
В Java нельзя передавать функцию в качестве аргумента другой функции.
На функциональном языке, если у вас есть функция
def addOne(i) = i + 1
вы можете передать это другой функции, которая, например, применяет его ко всем элементам списка.
В Java с
public static int addOne(int i) { return i + 1; }
нет способа сделать это.
Статические методы усложняют тестирование, потому что их нельзя заменить, это очень просто.
Как статические методы могут «имитировать» функции как объекты первого класса 1 ? Возможно, они хуже всего на этом фронте. Вы можете «имитировать» функции как объекты первого класса, создавая интерфейсы с одним методом, и действительно, Google Коллекции Java делают именно это в ряде мест (для предикатов, проекций и т. Д.). Этого нельзя сделать с помощью статических методов - нет способа (кроме отражения) передать концепцию «когда вы хотите применить функцию, используйте этот метод».
Нет, я не вижу, как здесь помогают статические методы. Они препятствуют изменению состояния (поскольку единственное доступное состояние - это глобальное состояние и любое изменяемое состояние, передаваемое через параметры), но они не помогают на стороне «функции как объекты первого класса».
C# имеет лучшую поддержку для этого (с лямбда-выражениями и делегатами), но даже это не так широко, как могло бы быть. (Сравните это, например, с F #.)
1 Начиная с Java 8, ссылки на методы позволяют преобразовывать методы в экземпляры соответствующих однопроходных интерфейсов, что делает все это более актуальным. Хотя еще в 2009 году до этого было еще далеко ...
Функциональная! = Функция, и для записи заявлю, что метод! = Функция ...
Java - это объектно-ориентированный язык со статической типизацией. Java также сохранила относительную чистоту в этом смысле, но это далеко не функциональный язык.
Хотя это правда, что вы можете имитировать поведение функционального программирования с помощью императивного программирования, вы никогда не получите того аккуратного синтаксиса, который вам нужен для лямбда-исчисления. В некотором смысле, если язык не поддерживает правильное лямбда-исчисление, это не функциональный язык программирования.
В C++ есть функции, но в C++ также есть классы. Таким образом, в C++ есть два типа функций: функции-члены и функции. Когда вы говорите «метод», вы имеете в виду функцию-член. Поскольку метод вызывается для экземпляра объекта. Но когда вы говорите статический метод, вы имеете в виду просто функцию (в смысле C/C++). Это просто словарь для обозначения элементов вашего кода. А в Java-коде не может существовать вне класса, метод подразумевает, что он принадлежит какому-то классу, то есть типу.
Пока ничего из того, что я сказал, не относится к функциональному программированию, но я думаю, что вы поняли, в чем ошиблись.
Я предлагаю вам взглянуть на чисто функциональные языки программирования, такие как Haskell или Erlang. Потому что в языках функционального программирования доводчиков, как правило, тоже нет.
Ваше заявление о том, что статические методы могут использоваться для имитации функций как объектов первого класса, звучит для меня очень странно. Это больше похоже на язык динамического программирования, чем на функциональное программирование.