статические методы делают Java псевдофункциональным языком?

Я думал о сообщении Миско Хевери о том, что статические методы в Java убивают тестируемость . Я хочу обсуждать не проблему тестируемости, а концепцию статических методов. Почему люди так его ненавидят?

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

Ответов (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. Потому что в языках функционального программирования доводчиков, как правило, тоже нет.

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

Мое самое большое возражение против статических методов состоит в том, что они не полиморфны и не используются объектно-ориентированным способом, вместо этого вам нужен класс (а не объект) для доступа к ним.

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

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