代码之家  ›  专栏  ›  技术社区  ›  Belun

什么是命名空间?用法呢?

  •  7
  • Belun  · 技术社区  · 14 年前
    1. 名称空间的用途是什么?

    2. 更重要的是,它们应该被用作Java中的对象(具有数据和功能并试图实现封装的东西)吗?这个想法有点牵强吗?:)

    3. 还是应该在Java中作为包使用呢?

    4. 或者应该更普遍地将它们用作模块系统或其他什么?

    4 回复  |  直到 11 年前
        1
  •  9
  •   Michał Marczyk    14 年前

    考虑到你使用了clojure标签,我想你会对clojure特定的答案感兴趣:

    名称空间的用途是什么?

    Culjure命名空间,Java包,Haskell/Python /任何模块…在很高的层次上,它们都是同一基本机制的不同名称,其主要目的是防止非平凡代码基中的名称冲突。当然,每个解决方案都有自己的小曲折和怪癖,它们在给定语言的上下文中是有意义的,在语言之外是没有意义的。剩下的答案将处理Clojure特有的曲折和怪癖。

    clojure命名空间组vars 包含函数(最常见)的容器、宏函数(编译器用来生成适当形式的宏扩展的函数,通常用 defmacro ;实际上,它们只是常规的clojure函数,尽管它们在编译器中注册的方式有一些魔力),偶尔还有各种“全局参数”(例如, clojure.core/*in* 对于标准输入),原子/refs等。Clojure 1.2中引入的协议设施具有很好的特性,即协议由vars支持,单独的协议功能也是如此;这是协议解决表达式问题的方法的关键(但可能不在该答案的范围内!).

    名称空间应该对以某种方式相关的var进行分组,这是有道理的。一般来说,创建一个名称空间是一个快速且廉价的操作,因此在开发的早期阶段使用一个名称空间是非常好的(而且确实是常见的),然后随着独立的功能块的出现,将它们分解到自己的名称空间中,清洗并重复……只有公共API的组成部分需要预先在名称空间之间分布(或者更确切地说,在稳定的发布之前),因为函数such和such驻留在名称空间so中,这当然是API的一部分。

    更重要的是,它们应该被用作Java中的对象(具有数据和功能并试图实现封装的东西)吗?这个想法有点牵强吗?:)

    通常情况下,答案是否定的。如果将它们作为具有许多静态方法、没有实例方法、没有公共构造函数并且通常没有状态的类来处理,那么可能会得到一张与事实不太远的图片(尽管有时可能会有一些“类数据成员”以变量的形式保存原子/引用);但是可以说,不使用使用Java ISH隐喻来套用成语,并将命名空间作为一组函数等等来对待,而不是“持有一组函数的类”或一些这样的事情。

    此一般规则有一个重要的例外:命名空间,其中包括 :gen-class 在他们 ns 形式。这意味着要实现一个Java类,它可以在后面被实例化,它可能有实例方法和每个实例状态等等。 Gen级 是一个互操作特性——纯Clojure代码通常应该避免它。

    还是应该在Java中作为包使用呢?

    它们提供了一些相同的目的:包被设计为服务(如上面已经提到的);类比,虽然它确实存在,但是,并不是有用的,只是因为包组合在一起的东西(Java类)根本不象把Coujess命名空间分组在一起的东西(Culjul-Var),各种各样的“访问L”。伊维斯” private / package / public 在Java中, {:private true} 或者不在clojure)工作非常不同等。

    也就是说,必须记住,在特定包中的名称空间和包/类之间存在一定的对应关系。名为的命名空间 foo.bar 编译时,生成一个名为 bar 在包装中 foo ;这尤其意味着名称空间名称应该至少包含一个点,因为所谓的单段名称显然会导致类被放入“默认包”中,从而导致各种各样的奇怪。(例如,我发现不可能让VisualVM的探查器注意到在单段名称空间中定义的任何函数。)

    也, deftype / defrecord -创建的类型不驻留在命名空间中 . 一 (defrecord Foo [...] ...) 命名空间所在文件中的窗体 酒吧酒吧 定义创建一个名为 Foo 在包装中 酒吧酒吧 . 使用类型 从另一个名称空间,必须 :import 班级 酒吧酒吧 包装—— :use / :require 不起作用,因为它们从名称空间拉入var,而记录/类型不是。

    因此,在这种特殊的情况下,名称空间和包之间存在某种对应关系,Clojure程序员希望利用某些较新的语言特性需要注意这些特性。一些人发现,这给那些不属于互操作领域的特性赋予了“互操作的味道”。( 破纪录 / 防御型 / defprotocol 是一种很好的抽象机制,即使我们忘记了它们在实现JVM上的平台速度方面的作用),而且在将来的Clojure版本中,这种风格可能会被去掉,因此 防御型 &可以将公司视为实现细节。

    或者应该更普遍地将它们用作模块系统或其他什么?

    他们 一个模块系统,这确实是它们应该如何使用的。

        2
  •  2
  •   Ultimate Gobblement    14 年前

    Java中的包有自己的命名空间,它提供类的逻辑分组。它还有助于防止命名冲突。例如,在Java中,您将找到JavaUTLDATE和JavaQL.DATE两个不同的类,它们的名称空间区分同一个名称。如果您尝试将两者导入到Java文件中,您将看到它不会编译。至少有一个版本需要使用其显式命名空间。

        3
  •  1
  •   Yannick Loiseau    14 年前

    从语言独立的观点来看,名称空间是一种隔离事物的方法(即封装在一个sens中)。这是一个更一般的概念(例如,请参见XML名称空间)。根据所使用的语言,您可以用多种方式“创建”名称空间:包、静态类、模块等。所有这些都为它们包含的对象/数据/函数提供了名称空间。这允许更好地组织代码,隔离特性,倾向于更好的代码重用和适应性(作为封装) 正如“python的禅”中所述,“名称空间是一个非常好的主意——让我们做更多的事情吧!”.

        4
  •  0
  •   Paulie Waulie    14 年前

    把它们当作类的容器。就像您有一个用于构建字符串的助手类,并且您希望它出现在业务层中一样,您将使用一个命名空间,如myapp.business.helpers。这允许类被包含在感性的位置中,因此当您或其他引用代码的人希望将它们组合在一起时,可以很容易地找到它们。对于另一个示例,如果要使用SQL连接帮助器类,则可能会使用如下内容:

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

    实际上,您将使用“using”语句,这样就不需要完全限定命名空间来声明变量。

    保罗