ColdFusion использует области this
и variables
для хранения ссылок на функции.Используемая ссылка зависит от того, как вызывается функция.Если функция вызывается с одного из братьев, используется ссылка variables
.Если функция вызывается извне, используется ссылка this
.
В следующем коде используется базовый класс для обеспечения функциональности смешивания.Функция $mixin
принимает экземпляр компонента и внедряет все его функции.Если происходит конфликт имен, обертка сначала вызовет mixin, а затем оригинальную функцию.Я генерирую новые имена функций как для исходных функций, так и для функций mixin, поэтому ссылки могут быть установлены в обеих областях.
Это было проверено на Lucee 5.2.8.50.
mixable.cfc
component {
function $mixin(obj) {
var meta = getComponentMetadata(obj);
for(var func in meta.functions) {
if(structKeyExists(this, func.name)) {
var orig = func.name & replace(createUUID(), '-', '', 'all');
var injected = func.name & replace(createUUID(), '-', '', 'all');
this[orig] = this[func.name];
variables[orig] = this[func.name];
this[injected] = obj[func.name];
variables[injected] = obj[func.name];
var wrapper = function() {
this[injected](argumentCollection=arguments);
return this[orig](argumentCollection=arguments);
};
this[func.name] = wrapper;
variables[func.name] = wrapper;
} else {
this[func.name] = obj[func.name];
return variables[func.name] = obj[func.name];
}
}
}
}
test.cfc
component extends="mixable" {
remote function foo() {
writeOutput("foo(), calling bar()<br>");
bar();
}
private function bar() {
writeOutput("bar()<br>");
}
}
mixin.cfc
component {
function foo() {
writeOutput("foo mixin, calling bar()<br>");
bar();
}
function myfunc() {
writeOutput("myfunc()<br>");
}
}
index.cfm
<cfscript>
t = new test();
t.$mixin(new mixin());
t.myfunc();
t.foo();
</cfscript>
Выход
myfunc()
foo mixin, calling bar()
bar()
foo(), calling bar()
bar()