考虑一个对象,该对象生成由另一个对象使用以生成结果的数据。流程封装在一个类中,中间数据不相关。
在下面的例子中,这个过程发生在构造上,没有问题。构造函数上的类型参数确保兼容的消费者/生产者。
public class ProduceAndConsume {
public interface Producer<T> {
T produce();
}
public interface Consumer<V> {
void consume(V data);
}
public <IntermediateType> ProduceAndConsume(Producer<? extends IntermediateType> producer, Consumer<IntermediateType> consumer) {
consumer.consume(producer.produce());
}
...
}
如果我希望存储对生产者/消费者的引用并在以后进行处理,那么代码将变为:
public class ProduceAndConsume<IntermediateType> {
public interface Producer<T> {
T produce();
}
public interface Consumer<V> {
void consume(V data);
}
private Producer<? extends IntermediateType> producer;
private Consumer<IntermediateType> consumer;
public ProduceAndConsume(Producer<? extends IntermediateType> producer, Consumer<IntermediateType> consumer) {
this.producer = producer;
this.consumer = consumer;
}
...
private void doLater() {
consumer.consume(producer.produce());
}
}
这向类引入了一个泛型类型参数,并强制在任何实现中指定它。
我的问题是,有什么办法可以避免这种情况吗?中间数据类型不由此类生成、存储或使用,并且与该类的用户无关。假设可以在某处指定 IntermediateType 类型参数,编译器拥有强制类型一致性所需的所有信息。
请注意,这是一个简化的示例,实际类会在构造后的某个时间异步并定期运行处理。
最佳答案
将生产者和消费者存储在具有类型变量的内部类中:
public class ProduceAndConsume {
private class Inner<IntermediateType> {
private Producer<? extends IntermediateType> producer;
private Consumer<IntermediateType> consumer;
// Constructor omitted.
private void doLater() {
consumer.consume(producer.produce());
}
}
private final Inner<?> inner;
public <IntermediateType> ProduceAndConsume(Producer<? extends IntermediateType> producer, Consumer<IntermediateType> consumer) {
this.inner = new Inner<>(producer, consumer);
}
private void doLater() { // Or just invoke inner.doLater() directly.
inner.doLater();
}
}
通过这种方式,您强制生产者和消费者在您稍后需要使用它们时相关,但之后您不需要在 ProduceAndConsume 实例中使用该类型信息。
Producer<String> stringProducer = ...;
Consumer<Object> objConsumer = ...;
// No externally-visible type variables.
ProduceAndConsume pac1 = new ProduceAndConsume(stringProducer, objConsumer);
但是编译器强制生产者和消费者的兼容性:
Consumer<Integer> integerConsumer = ...;
// Compiler error.
ProduceAndConsume pac2 = new ProduceAndConsume(stringProducer, integerConsumer);
关于java - 在不指定类类型参数的情况下强制类字段为相同的泛型类型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49231443/
Rackup通过Rack的默认处理程序成功运行任何Rack应用程序。例如:classRackAppdefcall(environment)['200',{'Content-Type'=>'text/html'},["Helloworld"]]endendrunRackApp.new但是当最后一行更改为使用Rack的内置CGI处理程序时,rackup给出“NoMethodErrorat/undefinedmethod`call'fornil:NilClass”:Rack::Handler::CGI.runRackApp.newRack的其他内置处理程序也提出了同样的反对意见。例如Rack
exe应该在我打开页面时运行。异步进程需要运行。有什么方法可以在ruby中使用两个参数异步运行exe吗?我已经尝试过ruby命令-system()、exec()但它正在等待过程完成。我需要用参数启动exe,无需等待进程完成是否有任何rubygems会支持我的问题? 最佳答案 您可以使用Process.spawn和Process.wait2:pid=Process.spawn'your.exe','--option'#Later...pid,status=Process.wait2pid您的程序将作为解释器的子进程执行。除
这是在Ruby中设置默认值的常用方法:classQuietByDefaultdefinitialize(opts={})@verbose=opts[:verbose]endend这是一个容易落入的陷阱:classVerboseNoMatterWhatdefinitialize(opts={})@verbose=opts[:verbose]||trueendend正确的做法是:classVerboseByDefaultdefinitialize(opts={})@verbose=opts.include?(:verbose)?opts[:verbose]:trueendend编写Verb
我有一些Ruby代码,如下所示:Something.createdo|x|x.foo=barend我想编写一个测试,它使用double代替block参数x,这样我就可以调用:x_double.should_receive(:foo).with("whatever").这可能吗? 最佳答案 specify'something'dox=doublex.should_receive(:foo=).with("whatever")Something.should_receive(:create).and_yield(x)#callthere
我正在为一个项目制作一个简单的shell,我希望像在Bash中一样解析参数字符串。foobar"helloworld"fooz应该变成:["foo","bar","helloworld","fooz"]等等。到目前为止,我一直在使用CSV::parse_line,将列分隔符设置为""和.compact输出。问题是我现在必须选择是要支持单引号还是双引号。CSV不支持超过一个分隔符。Python有一个名为shlex的模块:>>>shlex.split("Test'helloworld'foo")['Test','helloworld','foo']>>>shlex.split('Test"
我想在一个没有Sass引擎的类中使用Sass颜色函数。我已经在项目中使用了sassgem,所以我认为搭载会像以下一样简单:classRectangleincludeSass::Script::FunctionsdefcolorSass::Script::Color.new([0x82,0x39,0x06])enddefrender#hamlengineexecutedwithcontextofself#sothatwithintemlateicouldcall#%stop{offset:'0%',stop:{color:lighten(color)}}endend更新:参见上面的#re
我可以得到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/
我正在尝试修改当前依赖于定义为activeresource的gem:s.add_dependency"activeresource","~>3.0"为了让gem与Rails4一起工作,我需要扩展依赖关系以与activeresource的版本3或4一起工作。我不想简单地添加以下内容,因为它可能会在以后引起问题:s.add_dependency"activeresource",">=3.0"有没有办法指定可接受版本的列表?~>3.0还是~>4.0? 最佳答案 根据thedocumentation,如果你想要3到4之间的所有版本,你可以这