我在Spock中有这个代码:
then:
1 * dao.getByValue(Something.ONE, _ as String) >> {Something smth, String value ->
return createSomething(smth).withValue(value).build()
}
它看起来并不完全像,但你明白了。我想根据传递给方法的参数返回一个对象,在实际版本中,这个对象是从数据库加载的。
重点是我在很多地方都有这个电话,到处都看起来一模一样。我可以以某种方式提取这个闭包并在任何地方使用它,如:
then:
1 * dao.getByValue(Something.ONE, _ as String) >> Closures.makeSomething
我尝试使用Intellij提取功能,但它有点类型疯狂,在我手动编辑类型后我有奇怪的错误:
public static final Closure<Optional<Something>> makeSomething = { Something smth, String value ->
return createSomething(smth).withValue(value).build()
}
...
1 * dao.getByValue(Something.ONE, _ as String) >> makeSomething
org.codehaus.groovy.runtime.typehandling.GroovyCastException: Cannot cast object 'mypackage.MySpec$__clinit__closure1@1757cd72' with class 'mypackage.MySpec$__clinit__closure1' to class 'java.util.Optional'
即使那个没有用,我认为它会:
public static final Closure<Optional<Something>> makeSomething = { Something smth, String value ->
return createSomething(smth).withValue(value).build()
}
...
1 * dao.getByValue(Something.ONE, _ as String) >> {args -> makeSomething.call(args[0], args[1]) }
groovy.lang.MissingMethodException: No signature of method: mypackage.MySpec$__clinit__closure2.call() is applicable for argument types: (java.util.Arrays$ArrayList) values: [[mypackage.Something$$Lambda$6/1105423942@6f45df59, ...]]
我一般不擅长Groovy或Spock,我现在只是尝试这个。
修改
在@tim_yates建议之后的工作代码(整个交互在辅助方法中):
then:
interaction {
somethingCall(2, Something.TWO)
somethingCall(3, Something.ONE)
}
}
private void somethingCall(int times, Something something) {
times * dao.getByValue(something, _ as String) >> { Something smth, String value ->
return createSomething(smth).withValue(value).build()
}
}
不能使用我想要的代码(只有返回值在辅助方法中):
then:
2 * dao.getByValue(Something.TWO, _ as String) >> makeSomething
3 * dao.getByValue(Something.ONE, _ as String) >> makeSomething
}
public static final Closure<Optional<Something>> makeSomething = { Something smth, String value ->
return createSomething(smth).withValue(value).build()
}
如果我只是简单地内联每个>> makeSomething
并在那里写下它的身体,那么它就可以了。
答案 0 :(得分:0)
这里有一个概念性问题。你不能只是从前面的代码拆分闭包,因为如果你看它
dao.getByValue(something, _ as String) >> { Something smth, String value ->
return createSomething(smth).withValue(value).build()
}
您可能会注意到封闭内的smth
和value
从getByValue(something, _ as String)
获取其值。
现在,如果将内联闭包部分分解为独立的闭包实例,则会丢失该连接。首先,>> makeSomething
没有参数,其次你没有评估makeSomething
闭包,即在右手边你没有得到Optional
个实例而是Closure
个>> makeSomething(something, "dummy")
实例。为了评估闭包,你必须用参数调用它,即getByValue
之类的东西可以工作。但是这样你必须重复第一个>> { Something smth, String value -> makeSomething(smth, value) }
参数并为第二个未指定的参数组成一个虚拟对象,因为除了引入另一个像somethingCall(2, Something.TWO)
这样的闭包之外你没有简单的方法来引用它。但是你没有保存很多代码。
这是你的决定,如果这比#include "conio.h"
#include <iostream>
#include <thread>
#include <mutex>
#include <queue>
#include <atomic>
#include <condition_variable>
using namespace std;
enum state_t{ READ = 0, WRITE = 1 };
mutex mu;
condition_variable cv;
atomic<bool> running;
queue<int> buffer;
atomic<state_t> state;
void generate_test_data()
{
const int times = 5;
static int data = 0;
for (int i = 0; i < times; i++) {
data = (data++) % 100;
buffer.push(data);
}
}
void ProducerThread() {
while (running) {
unique_lock<mutex> lock(mu);
cv.wait(lock, []() { return !running || state == WRITE; });
if (!running) return;
generate_test_data(); //producing here
lock.unlock();
//notify consumer to start consuming
state = READ;
cv.notify_one();
}
}
void ConsumerThread() {
while (running) {
unique_lock<mutex> lock(mu);
cv.wait(lock, []() { return !running || state == READ; });
if (!running) return;
while (!buffer.empty()) {
auto data = buffer.front(); //consuming here
buffer.pop();
cout << data << " \n";
}
//notify producer to start producing
if (buffer.empty()) {
state = WRITE;
cv.notify_one();
}
}
}
int main(){
running = true;
thread producer = thread([]() { ProducerThread(); });
thread consumer = thread([]() { ConsumerThread(); });
//simulating gui thread
while (!getch()){
}
running = false;
producer.join();
consumer.join();
}
(我真的喜欢它)或者你选择我的设计构造更好。我不能为你做的是改变Groovy或Spock DSL语法只是因为你更喜欢它看起来不同。