Можно ли рассматривать Scala как «инверсию абстракции»? - PullRequest
3 голосов
/ 16 ноября 2010

Привет,

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

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

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

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

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

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


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

такого утверждения нет для функционального типа.

Ответы [ 4 ]

9 голосов
/ 16 ноября 2010

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

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

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

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

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

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

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

Итак, я думаю, что может быть доказано, что 1 верно. Давайте перейдем к следующему.

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

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

5 голосов
/ 16 ноября 2010

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

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

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

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

2 голосов
/ 16 ноября 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 являются чертами, можно использоватьсмешанное наследование, которое позволяет вам избегать ситуаций, подобных ситуации для Functors в C ++.Например, вы можете «модифицировать» Java-карту как функцию:

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
1 голос
/ 31 января 2011

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

...