Примесь ColdFusion, приводящая к подпрограммам, не может быть объявлена ​​более одного раза.

[Примечание: включение кода в ваш cfcs, как правило, является плохой практикой (см. ответы ниже), так что считайте это просто исследованием]

Подводя итог, у меня есть класс, подкласс и один метод, который переопределяется подклассом. Когда я жестко кодирую метод в дочернем классе, все работает нормально, когда я использую cfinclude для включения его в псевдоконструктор в стиле миксина, я получаю «Подпрограммы не могут быть объявлены более одного раза». ошибка.

Это кажется довольно простым. Чего мне не хватает: этого миксина?

родительский класс:

<cfcomponent >
    <cffunction name="hola" hint="i am the parent method">
        <cfreturn "hola - parent">
    </cffunction>
</cfcomponent>

дочерний класс:

<cfcomponent extends="mixinTestParent">
    <!---   this would work, successfully overridding parent method
    <cffunction name="hola" hint="i am the child method">
        <cfreturn "hola - child">
    </cffunction>--->

    <cfinclude template="mixinTestInc.cfm">

    <cffunction name="init" access="public" returntype="any" output="false">
        <cfreturn this>
    </cffunction>
</cfcomponent>

включать:

<cffunction name="hola" hint="i am the child method" access="public">
        <cfreturn "hola - child">
    </cffunction> 

бегун:

<cfset test = new mixinTestChild().init()>
<cfdump var="#test.hola()#">

заранее спасибо!!


person jbd    schedule 27.06.2012    source источник
comment
Я получаю ту же ошибку в ColdFusion 8, что и в 9+. Я бы сказал, что это ошибка, и ее следует зарегистрировать на bugbase.adobe.com. Кажется, что-то происходит не по порядку при компиляции класса, что не позволяет примеси дочернего класса переопределить родительский метод.   -  person Dan Short    schedule 27.06.2012
comment
Хм. Хорошо. Я могу это сделать, если кто-то еще не взвешивает и не имеет ответа. Я дам ему день. Кстати, вы знаете ожидаемый порядок компиляции? EG 1-включает, 2-псевдоконструктор...   -  person jbd    schedule 27.06.2012


Ответы (4)


Вы получаете сообщение об ошибке из-за способа создания экземпляра CFC.

Когда у вас есть hola() в родительском и hola() в дочернем, где дочерний расширяет родительский, при создании дочернего CFC он видит hola() в родительском и переопределяет его. Однако эта функция все еще существует в CFC.

Из дочернего CFC вы можете ссылаться как на hola() (определенный в дочернем CFC), так и на super.hola() (определенный в родительском).

Когда вы используете <cfinclude/>, создается экземпляр CFC, а содержимое включенного файла добавляется к миксу. Однако они не рассматриваются как часть модели наследования, как и "другие функции в этой CFC", поэтому вы получаете сообщение об ошибке.

Я согласен, что это плохая практика, когда делается вместо рефакторинга, но это хороший способ включить служебные пользовательские функции в микс, не делая их частью вашей модели.

person Adrian J. Moreno    schedule 27.06.2012
comment
Итак, во время выполнения, когда вы создаете экземпляр cfc, то, что «включено», каким-то образом оказывается за пределами модели наследования, но все же может быть частью вашего объекта как udf? я понимаю, что вы говорите, я думаю, но я все еще сбит с толку. (очевидно, что вся эта «плохая практика» попала в цель) - person jbd; 28.06.2012
comment
то есть эти другие функции, на которые вы ссылаетесь.... эта концепция описана где-нибудь в документах? - person jbd; 28.06.2012
comment
@jbd Я сомневаюсь, что вы найдете описание этой концепции в документации. Документы, как правило, о том, как вы должны создавать свой код, а не о тех странных способах, которыми мы заставляем код танцевать. :) - person Adrian J. Moreno; 28.06.2012

Я думаю, что использование cfinclude внутри cfc является плохой практикой. Кроме того, я думаю, что эта ссылка имеет отношение к вашей проблеме: http://www.bennadel.com/blog/972-CFCs-Are-Cached-CFIncludes-Are-Not.htm

person Jason M    schedule 27.06.2012
comment
хорошо - отметив, что это плохая практика в посте и что это больше упражнение, чем что-либо еще... - person jbd; 28.06.2012

Я думаю, вы могли бы заставить свои вещи работать, но делать то, что вы делаете, совсем не лучшая идея. Включает в себя работу очень хорошо для управления текстом и HTML и вывода информации на экран. Он не используется для включения функций.

Я нашел это для вас: http://www.justskins.com/forums/is-cfincludeing-from-cfcs-81144.html

Просто продолжение после обмена электронными письмами с Шоном Корфилдом, директором по архитектуре Macromedia.

Он сказал, что cfinclude файлов из функций CFC "плохая практика". Лично я считал хорошей практикой упростить CFC, но он сказал, что отказ от использования cfinclude побуждает людей «рефакторить свои CFC в более мелкие, более связные CFC».

Что касается копирования переменных «var» в область переменных во включаемых файлах, то это ошибка CFMX 6.1, которая, по словам Шона, исправлена ​​в CF7.

Шон не сказал конкретно, что использование cfinclude вызовет ошибки, но я склонен полагать, что эта практика действительно способствовала нашим странным ошибкам. Наши ошибки не были связаны с областью переменных, и я уверен, что они будут решены теперь, когда мы добавили ОЗУ на наш сервер, но это не значит, что cfinclude не способствовали этому.

В документации CF сказано, что можно использовать cfinclude, поэтому мы, вероятно, проведем некоторые тесты, прежде чем переносить весь наш код в саму CFC.

person Evik James    schedule 27.06.2012
comment
согласен, плохая практика, но все же приятно понять, что происходит под капотом... - person jbd; 28.06.2012

Просто чтобы добавить к ответу @iKnowKungFoo, проблема в том, что <cfinclude> не является сокращением для «вставьте сюда код, как если бы он был частью файла», как #include будет работать в C. Я говорю это, потому что это как большинство людей видят, что это работает.

В C #include является инструкцией компилятора (а не кодом C как таковым), и действительно, код из включенного файла фактически включается в файл до его компиляции.

В CF такого не бывает. Включенный файл компилируется отдельно, а затем происходит некоторая манипуляция Java (извините за технический термин ;-), чтобы создать впечатление, что включенный код встроен в код, который его включает (если это имеет смысл).

Теперь... каковы последствия этого? Когда файл CFM скомпилирован, функции внутри него скомпилированы как UDF, у которых нет концепции наследования, переопределения или чего-то подобного, потому что они не относятся к такому контексту. Только когда CFC компилируется, все это реализуется. В основном CFM не составляются с учетом объектно-ориентированного программирования, в то время как CFC учитывают именно это.

Таким образом, одно из правил UDF состоит в том, что может быть только одна функция с заданным именем для каждого запроса... это можно продемонстрировать, создав CFM, который включает ваш файл (тот, в котором есть hola()) дважды подряд: вы получим ошибку. Теперь, почему это правило на месте, я понятия не имею. Для меня функция — это просто переменная, поэтому второе объявление функции с тем же именем должно просто перезаписывать предыдущее. Однако CF всегда был таким, так что мы уже должны к этому привыкнуть. И в случае с вашим кодом, ваша UDF (в include) имеет то же имя, что и метод в вашем CFC, что достаточно для возникновения условия ошибки. В этом есть смысл.

Помогает ли это прояснить, что происходит и почему вы видите то, что видите?

person Adam Cameron    schedule 27.06.2012
comment
Java jiggery-pokery? Это связано с wibbly-wobbly, timey-wimey? :) - person Adrian J. Moreno; 28.06.2012