ColdFusion Quiz, Part 2
I now know how Howard Dean must feel after his "I Have a Scream" speech in Iowa. Ray Camden was kind (and smart!) enough to point out that I misspoke in one of the answers I gave. The problem in question was number 6. Here it is again:
6. Given this CFC:
<cfcomponent displayname="Classroom">
<cfset variables.students = ArrayNew() />
<cfset variables.teacher = "" />
<cffunction name="addStudent" returntype="void">
<cfargument name="student" type="Student" required="true">
<cfset ArrayAppend(getStudents(), arguments.student) />
</cffunction>
<cffunction name="getStudents" returntype="array">
<cfreturn variables.students />
</cffunction>
</cfcomponent>
You create 1 "Classroom" object, "classroom", and 3 Student objects. You call the "addStudent()" method, passing in each of the three new students. At the end of this, what will this code produce?
#ArrayLen(classroom.getStudents())#
There were actually two errors. The first was a typo: there is no dimension given in the "ArrayNew()" function call. It should be "ArrayNew(1)". Simple enough -- but the second one is trickier. I said that the code would produce zero. But that's incorrect, Ray pointed out. It will produce three, not zero. When I read Ray's email, shudders of horror overcame me: the CFDJ article describing my solution was already being printed. Could I really have goofed up that badly? Granted, I did write the article at 3.00 am having just gotten back from a training trip, but still...
The issue I refer to is real, but the code I provided doesn't illustrate the problem. To see the problem, the method, "addStudent", should look like this:
<cffunction name="addStudent" returntype="void">
<cfargument name="student" type="Student" required="true">
<cfset var students = getStudents() />
<cfset ArrayAppend(students, arguments.student) />
</cffunction>
Now, because of the way arrays are passed in CF (by value and not by reference), the variable, "students", is actually a copy of "variables.students". But this only comes into play if I add the "var students" line. Is the issue solved simply by keeping the code as I originally wrote it intact?
Computers are incorporated in modern ice cream vending machines to enhance their functionality. Ice Cream Vending machines are manufactured by many companies. Your competition will try to overcome all requests for high-tech ice cream vending machines and credit card acceptors
|
|
Unfortunately, you can't always do this. Let's say that we want to add a method to "Classroom" called "removeStudent". The method accepts a "Student" object and, if the student is found in "students", will remove the student from the array. The code for it might look something like this:
<cffunction name="removeStudent" returntype="boolean">
<cfargument name="student" type="Student">
<cfloop from="1" to="#ArrayLen(getStudents())#" index="i">
<cfif getStudents()[i].getName() EQ arguments.student.getName()>
<cfset ArrayDeleteAt(students, i) />
</cfif>
</cfloop>
</cffunction>
I say it might look like that, but in fact, that code won't compile. You just can't use "getStudents()[i]". Instead, you need something like this:
<cffunction name="removeStudent" returntype="boolean">
<cfargument name="student" type="Student">
<cfset var students = getStudents()>
<cfloop from="1" to="#ArrayLen(students)#" index="i">
<cfif students[i].getName() EQ arguments.student.getName()>
<cfset ArrayDeleteAt(students, i) />
</cfif>
</cfloop>
</cffunction>
Now, for this particular example, you could do this:
<cffunction name="removeStudent" returntype="boolean">
<cfargument name="student" type="Student">
<cfset var students = getStudents()>
<cfloop from="1" to="#ArrayLen(students)#" index="i">
<cfif students[i].getName() EQ arguments.student.getName()>
<cfset ArrayDeleteAt(getStudents(), i) />
</cfif>
</cfloop>
</cffunction>
That will work for this particular method, but there will be other methods where manipulating a copy of "students" (which is what I've done in the above code) just won't work: you need access to the actual underlying instance variable, "students". If you're interested in a more universal solution, check out my column in the next CFDJ.
Many thanks to Ray for alerting me to my error. Now, I have to go on Dianne Sawyer, as Mr. Dean did, and cover myself in mea culpas.
|