Можно ли рассматривать Scala как «инверсию абстракции»?

Привет,

Это провокационный вопрос, цель которого - открыть дискуссию о том, как инверсия абстракции воспринимается сообществом разработчиков. Мне действительно любопытно узнать, что вы думаете.

Во-первых, вот цитата из примеров инверсии абстракции, приведенных в Википедии: http://en.wikipedia.org/wiki/Abstraction_inversion

Создание объекта для представления функции является громоздким в объектно-ориентированных языках, таких как Java и C ++, в которых функции не являются объектами первого класса. В C ++ можно сделать объект «вызываемым», перегрузив оператор (), но по-прежнему часто необходимо реализовать новый класс, например функторы в STL.

Для меня функции являются первоклассным гражданином Scala, но когда мы используем Scala для генерации байт-кода Java, Scala создает определенный класс «поверх» Java, чтобы сделать возможным функциональное программирование ... можем ли мы рассматривать это как инверсию абстракции ?

То же самое может относиться к Clojure или к любому функциональному языку для JVM ... или даже к коллекциям Apache, например:

http://commons.apache.org/collections/apidocs/org/apache/commons/collections/Closure.html


Кстати, я не уверен в объективности статьи в Википедии. Например, когда речь идет о возможной инверсии абстракции в микроядре, в статье говорится: «Существует мнение, что конструкция микроядра является инверсией абстракции», но такого утверждения для функционального типа в ООП нет.


person Alois Cochard    schedule 16.11.2010    source источник


Ответы (4)


Вики-статья действительно слабая (представляет ли она собой инверсию абстракции? :), да и сама концепция несколько сомнительна. Но основная суть, по-видимому, заключается в том, что некий базовый элемент скрыт абстракцией, что вынуждает пользователей этой абстракции повторно реализовать его.

Например, со страницы обсуждения можно найти гораздо более интересный пример. Предположим, что у ЦП есть tan математическая функция, но нет sin или cos, а язык программирования реализован sin и cos в терминах tan, но не раскрывает сам tan. Программист, использующий этот язык, был бы вынужден реализовать tan в терминах sin и cos, которые сами по себе реализованы в терминах tan, что характеризует инверсию абстракции.

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

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

  1. Для JVM должен быть доступен "функциональный" примитив.
  2. Такой примитив должен был предлагать альтернативу тому, что делает Scala.

Что же такое функция? Как бы выглядела функция-примитив? В этом контексте «функция» означает данные, которые могут быть выполнены. Можно сказать, что весь код ассемблера, по сути, является данными, которые могут быть выполнены - только они не переносимы и, более того, не являются байт-кодом, поэтому не соответствуют принципам проектирования.

С другой стороны, на все методы в Java ссылаются с помощью идентификатора, с помощью которого Java находит код, который должен быть выполнен для иерархии классов данного объекта. Этот идентификатор не отображается, хотя может использоваться косвенно через отражение. Если бы он был открыт, и некоторые функции предлагали сказать «вызвать этот код», то, возможно, на его основе можно было бы построить функцию.

Итак, я думаю, что можно привести доводы в пользу того, что 1 верно. Переходим к следующему.

Если бы Java предлагала тип данных "метод", перестали бы ли функции Scala быть экземплярами класса? Нет, не пойдет. Одним из фундаментальных аспектов дизайна Scala является то, что каждый элемент работающей программы является объектом. «Примитивы», которые уже есть в Java, представлены, как если бы они были обычными объектами с методами, и если бы существовал примитив «метод», то и он.

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

person Daniel C. Sobral    schedule 16.11.2010
comment
ты тот !! + 1000 за глубокое понимание вопроса, за действительно хороший подробный ответ и за то, что вы являетесь коммитером FreeBSD! Большое спасибо, и я согласен, что эта статья - полная чушь ... ее нужно переписать или удалить. - person Alois Cochard; 17.11.2010

Реализация функции через объект не выполняется просто потому, что то, что возможно в JVM, напрямую связано с основной философией Scala.

все является объектом: функции, действующие лица, числовые литералы и т. д. Любой объект также может быть применимым (путем определения метода apply()), фактически не являясь подклассом FunctionN.

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

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

person Kevin Wright    schedule 16.11.2010

Нет, это нельзя рассматривать как инверсию абстракции. Причина проста: в Scala у вас есть выбор, какой уровень абстракции вы предпочитаете. В большинстве случаев удобнее писать

val f = 2 * (_:Int)
//--> f: (Int) => Int = 

f(21)
//--> res5: Int = 42

но сделать это "длинным" путем - не проблема:

val f = new Function1[Int,Int] { def apply(v:Int) = 2*v }
//--> f: java.lang.Object with (Int) => Int = 

f(21)
//--> res6: Int = 42

Поскольку FunctionN являются чертами, можно использовать смешанное наследование, которое позволяет избежать ситуаций, подобных той, что существует для функторов в C ++. Например. вы можете «модернизировать» Java-Map как функцию:

class JavaMap[K,V] extends java.util.HashMap[K,V] with Function1[K,V] {
    def apply(k:K) = get(k)
}

val m = new JavaMap[Int, String]
m.put(5,"five")
m(5)
//--> res8: String = five
person Landei    schedule 16.11.2010

Я не верю. Способ реализации первоклассных функций в Scala - это всего лишь деталь реализации.

person Artyom Shalkhakov    schedule 31.01.2011