Delphi允许使用var cluster = require('cluster'),
logger = require('./logger'),
maxJobs = Math.floor(require('os').cpus().length / 2),
activeJobs = 0;
if (cluster.isMaster) {
logger.enableConsole();
cluster.setupMaster({silent: true});
logger.log('workr', 'MaxJobs: ' + maxJobs);
setInterval(function () {
logger.log('workr', "Active: " + activeJobs);
}, 200);
for (var i = 0; i < maxJobs; i++) {
cluster.fork();
}
Object.keys(cluster.workers).forEach(function (id) {
cluster.workers[id].process.stdout.on('data', function (chunk) {
logger.log('workr', chunk);
});
cluster.workers[id].process.stderr.on('data', function (chunk) {
logger.log('error', 'Error in worker ' + id + ': ' + chunk);
});
cluster.workers[id].on('message', function (msg) {
if (msg.update !== undefined) {
activeJobs += msg.update ? 1 : -1;
}
});
})
cluster.on('exit', function (worker, code, signal) {
logger.log('workr', 'worker ' + worker.process.pid + ' died');
});
} else {
setTimeout(function () {
console.log('Adding 1');
process.send({ update: true });
setTimeout(function () {
console.log('Removing 1');
process.send({ update: false });
}, Math.random() * 500 + 1000);
}, Math.random() * 600 + 200);
}
关键字进行接口委派。
例如
implements
效果很好,但不适用于继承的接口。 (错误消息&#34;缺少接口方法ILev1.foo&#34的实现;)
IIndep1 = interface
function foo2: integer;
end;
IIndep2 = interface
function goo2: integer;
end;
TIndep1And2 = class(TInterfacedObject, IIndep1, IIndep2)
private
FNested : IIndep1; //e.g. passed via constructor or internally created (not shown here)
public
Constructor Create(AIndep1: IIndep1);
function goo2: integer;
property AsIndep1 : IIndep1 read FNested implements IIndep1;
end;
解决方法是添加额外的祖先类
ILev1 = interface
function foo: Integer;
end;
ILev2 = interface(ILev1)
function goo: Integer;
end;
TLev2Fails = class(TInterfacedObject, ILev1, ILev2) //Also fails with ILev2 alone (Error: "ILev1 not mentioned in interface list")
private
FNested : ILev1; //passed via constructor or internally created
public
Constructor Create(AILev1: ILev1);
function goo: Integer;
property AsLev1 : ILev1 read FNested implements ILev1;
end;
有没有办法避免包装类祖先?
[编辑]
只是关于接口委派的说明,使用TLev1Wrapper = class(TInterfacedObject, ILev1)
private
FNested : ILev1; //passed via constructor or internally created
public
Constructor Create(AILev1: ILev1);
property AsLev1 : ILev1 read FNested implements ILev1;
end;
TLev2Works = class(TLev1Wrapper, ILev2)
public
function goo: Integer;
end;
的目的是避免直接满足接口,而是将该需求传递给聚合或组合成员。提供完整的界面并手动委派给组成成员会失败使用implements
来指导界面所带来的好处。实际上,在这种情况下,implements
关键字和属性可能会被删除。
答案 0 :(得分:2)
这似乎是编译器试图强制执行the expectations (read: requirements) of IUnknown.QueryInterface:
对于任何一个对象,任何IUnknown接口的特定查询 对象的接口必须始终返回相同的指针值。
如果您能够在实现派生接口的同时委托基础接口的实现,那么:
obj := TLev2Fails.Create(otherLev1); // Assuming your class could compile
lev1 := obj as ILev1; // yields reference to otherLev1 implementor
lev2 := obj as ILev2; // yields reference to TLev2Fails instance
unk1 := lev1 as IUnknown; // returns IUnknown of otherLev1 implementor
unk2 := lev2 as IUnknown; // returns IUnknown of obj TLev2fails instance
如果您的嵌套对象被正确实现为 TAggregatedObject 派生类,则不会出现这种情况,但是编译器无法知道是否是这种情况,更不用说强制执行它了,而是出现了它只需要如果你实现派生接口,那么你还必须直接实现接口本身继承的任何接口。
在这种情况下,编译器错误不是很有帮助,虽然它可以被解读为告诉你你需要做什么,而不是为什么你需要在这种情况下这样做,这对编译器错误来说并不常见。
如果您希望在这种情况下委派,那么您必须“手动委派”。
虽然这失去了implements
设施的好处,但它至少保留了重复使用的好处,但不太方便。
注意:即使您的委托实现 基于 TAggregatedObject ,编译器仍然无法确定这些实现细节是否满足要求 QueryInterface ,因此您仍会收到此错误(即使使用委派接口的类引用)。
您仍必须手动委派。
说了这么多,我现在无法看到当接口没有继承关系的情况下,这有什么不同,但很可能这是有效的,我只是没有完成所有必要的工作'想实验'向我自己证明。 :)
可能是编译器在它认为可能/应该存在的情况下只是格外谨慎,而且文档根本没有提到implements
导致的限制。
或者它可能是编译器中的一个错误,尽管我认为行为有足够明显的原因,并且行为本身如此完善且一致(在Delphi 7中重现完全相同的行为)相关的遗漏文档是更可能的解释。
答案 1 :(得分:0)
有没有办法避免包装类祖先?
不,继承的接口必须绑定到祖先类。由于here解释的原因,Delphi不会隐式绑定继承的接口。此外,它不能绑定到当前类,除非它手动将所有调用委托给组合项。
我们只剩下一个选项。一个祖先包装类,我们可以绑定ILev1