我经常看到类似 List<String> list = new ArrayList<>(); 的声明或 Set<String> set = new HashSet<>();对于类中的字段。对我来说,使用变量类型的接口(interface)来提供实现的灵 active 是非常有意义的。上面的例子仍然定义了哪种 Collection必须分别使用 s ,分别允许哪些操作以及在某些情况下它应该如何表现(由于文档)。
现在考虑实际上只有 Collection 的功能的情况。 (甚至 Iterable )接口(interface)需要使用类中的字段和 Collection 的种类实际上并不重要,或者我不想过度指定它。所以我选择例如HashSet作为实现并将该字段声明为 Collection<String> collection = new HashSet<>(); .
那么该字段实际上应该是 Set 类型吗?在这种情况下?这种声明是不是不好的做法,如果是,为什么?或者尽可能少地指定实际类型(并仍然提供所有必需的方法)是一种很好的做法。我问这个的原因是因为我几乎没有见过这样的声明,最近我在我只需要指定 Collection 的功能的情况下得到了更多。界面。
例子:
// Only need Collection features, but decided to use a LinkedList
private final Collection<Listener> registeredListeners = new LinkedList<>();
public void init() {
ExampleListener listener = new ExampleListener();
registerListenerSomewhere(listener);
registeredListeners.add(listener);
listener = new ExampleListener();
registerListenerSomewhere(listener);
registeredListeners.add(listener);
}
public void reset() {
for (Listener listener : registeredListeners) {
unregisterListenerSomewhere(listener);
}
registeredListeners.clear();
}
最佳答案
由于您的示例使用私有(private)字段,因此隐藏实现类型并不重要。您(或维护此类的任何人)可以随时查看字段的初始值设定项以了解它是什么。
但是,根据它的使用方式,可能值得为该字段声明一个更具体的接口(interface)。将其声明为 List表示允许重复并且排序很重要。将其声明为 Set表示不允许重复并且排序不重要。如果有一些重要的东西,您甚至可以声明该字段具有特定的实现类。例如,将其声明为 LinkedHashSet表示不允许重复,但排序很重要。
如果类型出现在类的公共(public) API 中,以及对此类的兼容性约束是什么,则选择是否使用接口(interface)以及使用什么接口(interface)变得更加重要。例如,假设有一个方法
public ??? getRegisteredListeners() {
return ...
}
Collection .这为底层实现提供了相当程度的抽象,但它也为调用者提供了一组合理的操作。调用者可以迭代、获取大小、进行包含检查或将所有元素复制到另一个集合。Iterable作为最抽象的接口(interface)返回。它所做的只是允许调用者进行迭代。有时这就是全部必要的,但与 Collection 相比可能有些限制。 .Stream .如果您认为调用者可能想要使用流的操作(例如过滤器、映射、查找等)而不是迭代或使用集合操作,这将很有帮助。Collection或 Iterable ,您需要确保返回不可修改的 View 或制作防御性副本。否则,调用者可能会修改您的类的内部数据,这可能会导致错误。 (是的,即使是 Iterable 也可以允许修改!考虑获取一个 Iterator 然后调用 remove() 方法。)如果你返回一个 Stream ,您无需担心,因为您不能使用 Stream修改底层源。var ),而对于私有(private)字段则无关紧要,因为那些(几乎)根据定义只影响它们所在的类重新声明。但是,“编程到接口(interface)”原则对于 API 签名非常重要,因此在这些情况下,您确实需要考虑接口(interface)类型。私有(private)领域,不是那么多。public 。)
关于HashSet 或其他实现的 Java 变量类型集合?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55601504/
我试图在一个项目中使用rake,如果我把所有东西都放到Rakefile中,它会很大并且很难读取/找到东西,所以我试着将每个命名空间放在lib/rake中它自己的文件中,我添加了这个到我的rake文件的顶部:Dir['#{File.dirname(__FILE__)}/lib/rake/*.rake'].map{|f|requiref}它加载文件没问题,但没有任务。我现在只有一个.rake文件作为测试,名为“servers.rake”,它看起来像这样:namespace:serverdotask:testdoputs"test"endend所以当我运行rakeserver:testid时
我正在寻找执行以下操作的正确语法(在Perl、Shell或Ruby中):#variabletoaccessthedatalinesappendedasafileEND_OF_SCRIPT_MARKERrawdatastartshereanditcontinues. 最佳答案 Perl用__DATA__做这个:#!/usr/bin/perlusestrict;usewarnings;while(){print;}__DATA__Texttoprintgoeshere 关于ruby-如何将脚
我正在查看instance_variable_set的文档并看到给出的示例代码是这样做的:obj.instance_variable_set(:@instnc_var,"valuefortheinstancevariable")然后允许您在类的任何实例方法中以@instnc_var的形式访问该变量。我想知道为什么在@instnc_var之前需要一个冒号:。冒号有什么作用? 最佳答案 我的第一直觉是告诉你不要使用instance_variable_set除非你真的知道你用它做什么。它本质上是一种元编程工具或绕过实例变量可见性的黑客攻击
我正在编写一个gem,我必须在其中fork两个启动两个webrick服务器的进程。我想通过基类的类方法启动这个服务器,因为应该只有这两个服务器在运行,而不是多个。在运行时,我想调用这两个服务器上的一些方法来更改变量。我的问题是,我无法通过基类的类方法访问fork的实例变量。此外,我不能在我的基类中使用线程,因为在幕后我正在使用另一个不是线程安全的库。所以我必须将每个服务器派生到它自己的进程。我用类变量试过了,比如@@server。但是当我试图通过基类访问这个变量时,它是nil。我读到在Ruby中不可能在分支之间共享类变量,对吗?那么,还有其他解决办法吗?我考虑过使用单例,但我不确定这是
我可以得到Infinity和NaNn=9.0/0#=>Infinityn.class#=>Floatm=0/0.0#=>NaNm.class#=>Float但是当我想直接访问Infinity或NaN时:Infinity#=>uninitializedconstantInfinity(NameError)NaN#=>uninitializedconstantNaN(NameError)什么是Infinity和NaN?它们是对象、关键字还是其他东西? 最佳答案 您看到打印为Infinity和NaN的只是Float类的两个特殊实例的字符串
我不确定传递给方法的对象的类型是否正确。我可能会将一个字符串传递给一个只能处理整数的函数。某种运行时保证怎么样?我看不到比以下更好的选择:defsomeFixNumMangler(input)raise"wrongtype:integerrequired"unlessinput.class==FixNumother_stuffend有更好的选择吗? 最佳答案 使用Kernel#Integer在使用之前转换输入的方法。当无法以任何合理的方式将输入转换为整数时,它将引发ArgumentError。defmy_method(number)
我真的很习惯使用Ruby编写以下代码:my_hash={}my_hash['test']=1Java中对应的数据结构是什么? 最佳答案 HashMapmap=newHashMap();map.put("test",1);我假设? 关于java-等价于Java中的RubyHash,我们在StackOverflow上找到一个类似的问题: https://stackoverflow.com/questions/22737685/
我是一个Rails初学者,但我想从我的RailsView(html.haml文件)中查看Ruby变量的内容。我试图在ruby中打印出变量(认为它会在终端中出现),但没有得到任何结果。有什么建议吗?我知道Rails调试器,但更喜欢使用inspect来打印我的变量。 最佳答案 您可以在View中使用puts方法将信息输出到服务器控制台。您应该能够在View中的任何位置使用Haml执行以下操作:-puts@my_variable.inspect 关于ruby-on-rails-如何在我的R
我有一个用户工厂。我希望默认情况下确认用户。但是鉴于unconfirmed特征,我不希望它们被确认。虽然我有一个基于实现细节而不是抽象的工作实现,但我想知道如何正确地做到这一点。factory:userdoafter(:create)do|user,evaluator|#unwantedimplementationdetailshereunlessFactoryGirl.factories[:user].defined_traits.map(&:name).include?(:unconfirmed)user.confirm!endendtrait:unconfirmeddoenden
有时我需要处理键/值数据。我不喜欢使用数组,因为它们在大小上没有限制(很容易不小心添加超过2个项目,而且您最终需要稍后验证大小)。此外,0和1的索引变成了魔数(MagicNumber),并且在传达含义方面做得很差(“当我说0时,我的意思是head...”)。散列也不合适,因为可能会不小心添加额外的条目。我写了下面的类来解决这个问题:classPairattr_accessor:head,:taildefinitialize(h,t)@head,@tail=h,tendend它工作得很好并且解决了问题,但我很想知道:Ruby标准库是否已经带有这样一个类? 最佳