2010-09-01 4 views
5
  1. Какова цель пространства имен?Что такое пространства имен? как насчет обычаев?

  2. и, что более важно, должны ли они использоваться как объекты в java (вещи, которые имеют данные и функции и которые пытаются достичь инкапсуляции)? эта идея далека? :)

  3. или они должны использоваться как пакеты в java?

  4. или должны ли они использоваться в целом как модульная система или что-то еще?

ответ

7

Учитывая, что вы используете тег Clojure, я полагаю, что вы будете заинтересованы в Clojure-специфического ответа:

что цель пространств имен?

Clojure пространств имен, Java-пакеты, Haskell/Python/все модули ... На очень высоком уровне, они все разные названия для того же основного механизма, главной целью которого является предотвращение конфликтов имен в нетривиальной . базы кода Конечно, каждое решение имеет свои собственные небольшие завихрения и причуды, которые имеют смысл в контексте данного языка и не имеют смысла вне его. Остальная часть этого ответа будет касаться завихрений и причуд, характерных для Clojure.

Clojure пространства имена группы Vars, которые являются контейнерами, проведение функции (чаще всего), макро-функция (функции, используемой компилятором для генерации macroexpansions соответствующих форм, как правило, определенных с defmacro, на самом деле они являются лишь регулярными функциями Clojure, хотя есть какая-то магия к способу регистрации в компиляторе), а иногда и различные «глобальные параметры» (скажем, clojure.core/*in* для стандартного ввода), Atoms/Refs и т. д. Протокол, введенный в Clojure 1.2, имеет приятное свойство, которое протоколы поддерживаются Vars, а также отдельные функции протокола; это ключ к тому, как протоколы представляют собой решение проблемы выражения (что, однако, возможно, выходит за рамки этого ответа!).

Понятно, что пространства имен должны группировать Vars, которые каким-то образом связаны. В общем, создание пространства имен является быстрой операцией &, поэтому совершенно нормально (и, как обычно,) использовать одно пространство имен на ранних этапах разработки, а затем, когда появляются независимые куски функциональности, выставляйте их в свои собственные пространства имен, rinse & repeat ... Только вещи, которые являются частью публичного API, должны быть распределены между пространствами имен впереди (а точнее: до стабильной версии), поскольку тот факт, что функция такая-то и находится в пространстве имен, и, следовательно, является частью API.

и, что более важно, должны ли они использоваться как объекты в java (вещи, которые имеют данные и функции и которые пытаются достичь инкапсуляции)? эта идея далека? :)

Обычно ответ отрицательный. Вы можете получить изображение не слишком далеко от истины, если вы подходите к ним как к классам с множеством статических методов, без методов экземпляра, не к публичным конструкторам и часто не к состоянию (хотя иногда могут быть некоторые «члены данных класса» в форме Вары, удерживающие атомы/Refs); но, возможно, более полезно не пытаться применять метафоры Java-иш к идиомам Clojure и приближаться к пространству имен как к группе функций и т. д., а не к «классу, содержащему группу функций» или к какой-то такой вещи.

Существует важное исключение из этого общего правила: пространства имен, которые включают :gen-class в их форме ns. Они предназначены именно для реализации Java-класса, который впоследствии может быть создан, что может иметь методы экземпляра и состояние каждого экземпляра и т. Д. Обратите внимание, что :gen-class - это функция взаимодействия - чистый код Clojure должен вообще избегать этого.

или они должны использоваться как пакеты в java?

Они служат для некоторых целей, предназначенных для обслуживания (как уже упоминалось выше); аналогия, хотя это, безусловно, есть, не так полезна, однако, только потому, что вещи, которые группируются вместе (классы Java), совсем не похожи на то, что объединяет пространства имен Clojure (Clojure Vars), различные «уровни доступа», (private/package/public в Java, {:private true} или не в Clojure) работают очень по-разному и т.д.

это, как говорится, надо помнить, что существует определенное соответствие между пространствами имен и пакетов/классов, проживающих в отдельных пакетах. Пространство имен, называемое foo.bar, при компиляции производит класс bar в пакете foo; это означает, в частности, что имена пространств имен должны содержать по крайней мере одну точку, так как так называемые односегментные имена, по-видимому, приводят к тому, что классы помещаются в «пакет по умолчанию», что приводит к любым видам странности. (Например.Я считаю, что невозможно иметь профилировщика уведомление VisualVM в любые функции, определенные в пространствах имен одного сегмента.)

Кроме того, deftype/defrecord -created типы не находятся в пространствах имен. Форма (defrecord Foo [...] ...) в файле, где определено пространство имен foo.bar, создает класс Foo в пакете foo.bar. Чтобы использовать тип Foo из другого пространства имен, нужно было бы :import класс Foo из пакета foo.bar - :use/:require не работал, поскольку они вытягивают Vars из пространств имен, в которых нет записей/типов.

Таким образом, в данном конкретном случае существует определенное соответствие между пространствами имен и пакетами, о которых должны помнить программисты Clojure, которые хотят использовать некоторые из новых функций языка. Некоторые считают, что это дает «эффект взаимодействия» с функциями, которые иначе не считаются принадлежащими к сфере взаимодействия. (defrecord/deftype/defprotocol - хороший механизм абстракции, даже если мы забываем об их роли в достижении скорости платформы на JVM) и, безусловно, возможно, что в какой-то будущей версии Clojure этот вкус может быть устранен, так что соответствие имени названия/имени пакета для deftype & Co. может рассматриваться как деталь реализации.

или должны ли они использоваться в целом как модульная система или что-то еще?

Они являются модульная система, и это на самом деле, как они должны быть использованы.

0

Думайте о них как о контейнерах для занятий. Как и в случае, если у вас был вспомогательный класс для построения строк, и вы хотели его на своем бизнес-уровне, вы использовали бы пространство имен, такое как MyApp.Business.Helpers. Это позволяет вашим классам содержаться в чувственных местах, поэтому, когда вы или какой-либо другой, ссылающийся на ваш код, хотите их использовать, они могут быть легко расположены. В качестве другого примера, если вы хотите, чтобы потреблять SQL хелперов соединения класса вы, вероятно, использовать что-то вроде:

MyApp.Data.SqlConnectionHelper sqlHelper = new MyApp.Data.SqlConnectionHelper();

В реальности вы бы использовать «используя» заявление, так что вы не должны были бы полностью определить пространство имен просто для объявления переменной.

Пол

2

пакет в Java имеет свое собственное пространство имен, которое обеспечивает логическую группировку классов. Это также помогает предотвратить коллизии имен. Например, в java вы найдете java.util.Date и java.sql.Date - два разных класса с тем же именем, которые различаются по их пространству имен. Если вы попытаетесь импортировать оба в java-файл, вы увидите, что он не будет компилироваться. По крайней мере одна версия должна будет использовать свое явное пространство имен.

1

От языкового независимого вида пространства имен - это способ изолировать вещи (т. Е. Инкапсулировать в смысле). Это более общая концепция (см., Например, пространства имен xml). Вы можете «создать» пространства имен несколькими способами, в зависимости от используемого вами языка: пакетов, статических классов, модулей и т. Д. Все они предоставляют пространства имен объектам/данным/функциям, которые они содержат. Это позволяет лучше организовать код, изолировать функции, стремится к лучшему повторному использованию кода и адаптивности (как инкапсуляция) Как указано в «Zen of Python», «Пространства имен - одна хорошая идея - давайте сделаем больше!» ,

Смежные вопросы