我一直对 Java 和 C# 如何处理命名空间的概念感到困惑。
首先,一些编程语言中命名空间污染的例子:
使用命名空间 std 用于 C++。
行业中的每个人都对此表示不满,但初学者在开始编程时仍会被教导这样做。 Here's a SO question about the advice for handling global namespaces
在 Python 中导入 math.*
在学习 Python 类(class)时,有人告诉我不建议这样做,因为它会污染命名空间,并且首先允许在没有 Math.functionname 的情况下访问数学库中的所有方法,但可能会导致冲突编写具有重复名称的方法。由于它导入了所有函数,甚至是那些未使用的函数,因此它显然也会给解释器带来更多的工作。
在 Ocaml 中打开模块 在顶层或 ML 文件中执行此操作 Might cause conflicts在命名方面也是如此。尤其是在编写库时。
问题:
C# 和 Java 中是否存在“命名空间污染”(即在编写方法时导入大量可能导致冲突的方法)(它们在许多方面相似)?为什么不呢?
当然还有相关的问题太相似了,不能再问了:
-是因为也许我们必须明确地@Override 东西还是有某种预防措施?
-或者它存在,但它不是一件事,因为它不会像“使用命名空间标准”那样造成严重破坏,而且我不知道它对于学术类(class)之外的软件开发来说相对较新?
示例
我发现自己在 C# 中使用很多库,以避免必须为变量重新键入 namespace ,例如 XElement
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
//the ones above are auto-generated by Visual Studio, too
using System.Xml.Linq;
将避免我每次创建 XElement 时都必须执行 System.Xml.Linq.XElement。就像我们总是必须在 C++ 中做 std::cout
或者在我经常看到的Java中:import java.util.linkedlist,甚至是import java.util.*
如果我的类在其他地方使用,这些会不会造成命名空间污染?还是因为它们只会“污染”特定的类范围,而不是可能导入或继承我的类的其他类?
我尝试搜索答案,但找不到答案,不过我可能用错了搜索措辞。
编辑 2015 年 4 月 20 日:
正如@RealSkeptic 所提到的,Java 通配符导入也是不鼓励的。 source
除了下面接受的答案和答案之外,Java 和 C# 中的导入包含在它们自身中,因此即使有人使用通配符类型的导入将未使用的方法名称添加到命名空间,它也不会影响其他类。在类级别上,如果确实发生名称冲突,Java 和 C# 编译器将抛出一个错误,引用不明确的导入,并且无法进一步编译,直到问题得到解决(例如通过重命名函数)。
最佳答案
正如其他人已经指出的那样,命名空间污染问题在 Java 中并不像在 C++ 中那样突出。命名空间污染在 C++ 中是一个问题(因此首先被称为“污染”)的主要原因是它可能导致其他模块中的错误。这在 Why is “using namespace std;” considered bad practice? 中有更详细的解释。 .
(这里的问题是,这可能不仅仅指编译错误:对于编译错误,你被迫做某事并解决歧义。真正令人担忧的是它可能会导致代码仍然可以正确编译,但之后只是调用了错误的函数!)
在 Java 中,每个 import 只影响包含它的文件。这意味着上面提到的污染仍然可以在一个文件中本地发生。 (可以说:实际上造成命名空间污染的只是作者的问题,这很公平)
类似于上述链接中的情况:假设您正在使用两个库,“foo”和“bar”。出于懒惰(或缺乏最佳实践知识),您正在使用通配符导入:
import foo.*:
import bar.*:
class MyClass {
void someMethod() {
// Assume that this class is from the "foo" librariy, and the
// fully qualified name of this class is "foo.Example"
Example e = new Example();
}
}
现在假设您升级了“bar”库的版本。新版本包含一个名为bar.Example 的类。那么上面的代码将无法编译,因为对类 Example 的引用不明确。
顺便说一下,static imports 也会出现同样的问题。 .它更加微妙和微妙,碰撞的可能性更大。这就是为什么他们说您应该非常谨慎地使用静态导入。
附注:当然,这些冲突和歧义很容易解决。您始终可以使用完全限定名称。大多数现代 Java IDE 都提供了组织/优化导入的功能。例如,在 Eclipse 中,您始终可以按 CTRL+Shift+O,这将(取决于 Preferences->Java->代码样式->组织导入)将所有通配符导入替换为单个的。
关于java - Java 或 C# 中是否存在命名空间污染(如在 C++ 中)?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29707809/
给定这段代码defcreate@upgrades=User.update_all(["role=?","upgraded"],:id=>params[:upgrade])redirect_toadmin_upgrades_path,:notice=>"Successfullyupgradeduser."end我如何在该操作中实际验证它们是否已保存或未重定向到适当的页面和消息? 最佳答案 在Rails3中,update_all不返回任何有意义的信息,除了已更新的记录数(这可能取决于您的DBMS是否返回该信息)。http://ar.ru
我的瘦服务器配置了nginx,我的ROR应用程序正在它们上运行。在我发布代码更新时运行thinrestart会给我的应用程序带来一些停机时间。我试图弄清楚如何优雅地重启正在运行的Thin实例,但找不到好的解决方案。有没有人能做到这一点? 最佳答案 #Restartjustthethinserverdescribedbythatconfigsudothin-C/etc/thin/mysite.ymlrestartNginx将继续运行并代理请求。如果您将Nginx设置为使用多个上游服务器,例如server{listen80;server
这个问题在这里已经有了答案:Checktoseeifanarrayisalreadysorted?(8个答案)关闭9年前。我只是想知道是否有办法检查数组是否在增加?这是我的解决方案,但我正在寻找更漂亮的方法:n=-1@arr.flatten.each{|e|returnfalseife
我真的很习惯使用Ruby编写以下代码:my_hash={}my_hash['test']=1Java中对应的数据结构是什么? 最佳答案 HashMapmap=newHashMap();map.put("test",1);我假设? 关于java-等价于Java中的RubyHash,我们在StackOverflow上找到一个类似的问题: https://stackoverflow.com/questions/22737685/
我有一个包含多个键的散列和一个字符串,该字符串不包含散列中的任何键或包含一个键。h={"k1"=>"v1","k2"=>"v2","k3"=>"v3"}s="thisisanexamplestringthatmightoccurwithakeysomewhereinthestringk1(withspecialcharacterslike(^&*$#@!^&&*))"检查s是否包含h中的任何键的最佳方法是什么,如果包含,则返回它包含的键的值?例如,对于上面的h和s的例子,输出应该是v1。编辑:只有字符串是用户定义的。哈希将始终相同。 最佳答案
我需要检查DateTime是否采用有效的ISO8601格式。喜欢:#iso8601?我检查了ruby是否有特定方法,但没有找到。目前我正在使用date.iso8601==date来检查这个。有什么好的方法吗?编辑解释我的环境,并改变问题的范围。因此,我的项目将使用jsapiFullCalendar,这就是我需要iso8601字符串格式的原因。我想知道更好或正确的方法是什么,以正确的格式将日期保存在数据库中,或者让ActiveRecord完成它们的工作并在我需要时间信息时对其进行操作。 最佳答案 我不太明白你的问题。我假设您想检查
我的日期格式如下:"%d-%m-%Y"(例如,今天的日期为07-09-2015),我想看看是不是在过去的七天内。谁能推荐一种方法? 最佳答案 你可以这样做:require"date"Date.today-7 关于ruby-检查日期是否在过去7天内,我们在StackOverflow上找到一个类似的问题: https://stackoverflow.com/questions/32438063/
这里有一个很好的答案解释了如何在Ruby中下载文件而不将其加载到内存中:https://stackoverflow.com/a/29743394/4852737require'open-uri'download=open('http://example.com/image.png')IO.copy_stream(download,'~/image.png')我如何验证下载文件的IO.copy_stream调用是否真的成功——这意味着下载的文件与我打算下载的文件完全相同,而不是下载一半的损坏文件?documentation说IO.copy_stream返回它复制的字节数,但是当我还没有下
我们的git存储库中目前有一个Gemfile。但是,有一个gem我只在我的环境中本地使用(我的团队不使用它)。为了使用它,我必须将它添加到我们的Gemfile中,但每次我checkout到我们的master/dev主分支时,由于与跟踪的gemfile冲突,我必须删除它。我想要的是类似Gemfile.local的东西,它将继承从Gemfile导入的gems,但也允许在那里导入新的gems以供使用只有我的机器。此文件将在.gitignore中被忽略。这可能吗? 最佳答案 设置BUNDLE_GEMFILE环境变量:BUNDLE_GEMFI
如何在ruby中调用C#dll? 最佳答案 我能想到几种可能性:为您的DLL编写(或找人编写)一个COM包装器,如果它还没有,则使用Ruby的WIN32OLE库来调用它;看看RubyCLR,其中一位作者是JohnLam,他继续在Microsoft从事IronRuby方面的工作。(估计不会再维护了,可能不支持.Net2.0以上的版本);正如其他地方已经提到的,看看使用IronRuby,如果这是您的技术选择。有一个主题是here.请注意,最后一篇文章实际上来自JohnLam(看起来像是2009年3月),他似乎很自在地断言RubyCL