Reputation: 11391
Inside a ColdFusion component I declare a function like this:
string function render(required Array actions) output=false {
//...
}
So the function parameter can only accept an Array. However, I need to make sure the array contains only "ActionItem" objects (there is an ActionItem.cfc component)
Is there a way in ColdFusion to type-hint the array contents? What solution do you suggest in this case?
Upvotes: 4
Views: 1553
Reputation: 43728
Actually, ColdFusion has some support for arrays type validation (which is not to be confused with typed arrays), but it only seems to work with custom components, not for primitive types. However I haven't found any other documentation on this feature other than this blog entry.
Let's suppose we have a SomeObject
component.
We could write:
<cffunction name="testArrayTypeValidation">
<cfargument name="someObjects" type="SomeObject[]" required="yes">
<cfdump var="#someObjects#">
</cffunction>
And then call our function like:
<cfset testArrayTypeValidation([new SomeObject()])>
However, beware that it will only validate the type of the first item in the array, which means that the following would also work:
<cfset testArrayTypeValidation([new SomeObject(), 'some string'])>
Also, it doesn't seem to work for primitive types, so you cannot use type="string[]"
for instance, which is kind of sad.
For primitive types, you will have to implement your own concrete wrapper class which will ensure to contain only primitives of a certain type and use that class as an argument type.
Upvotes: 3
Reputation: 520
You could write a function to check the array. It would take 2 arguments, your array to check and the object type, and return a boolean result. The function would loop over the object and determine if the value at that index is an object, and if so look at it's meta data to determine if it is the type you want. The first time you find a bad element, you set a false return value, and abort the loop. It's not the most ideal solution, but it would work and be generic that you could use it as a check in any of your other components.
Also, just for your own sanity, I would definitely reference everything the way you expect it:
public model.bean.Foo[] function Read(required model.bean.Foo aBean) {...}
So that function expects a Foo object as an argument and returns an array of Foo objects. Just make sure you add a mapping to your initial path point ("model" in my case) so CF will know where to start looking for it. In the Application.cfc, you'd add something like:
this.mappings["/model"] = getDirectoryFromPath(expandPath(".")) & "myProjectDir/model";
Upvotes: 0
Reputation: 9857
To elaborate on my comment, the following is an outline of a possible collection you could create.
I love collection classes and the ArrayCollection
class here is very reusable and allows you to use the wrapped array as an object.
component ArrayCollection()
{
public function init()
{
variables.collection = [];
return this;
}
public any function get();
public function set(required array collection);
public function add(required any item);
public function remove();
}
component ActionItemCollection extends ArrayCollection
{
public function add(required ActionItem item);
public ActionItem function get();
}
component otherComponnet{
public string function render(required ActionItemCollection actions)
{
}
}
It my be overkill in some circumstances, however it allows you to enfore the type of items within the array!
Upvotes: 4
Reputation: 29870
In short, as Peter has said in his comment, the basic answer is "you can't". ColdFusion doesn't have the notion of typeful arrays.
There's two ways around this. Firstly the brute-force approach of validating each array item as you need it, making sure it's the type you need. This is what Peter suggests, and generally what I'd do.
Failing that you could implement an ActionItemCollection.cfc
which itself contains an array of ActionItems
, and leave it to ActionItemCollection.cfc
to only accept ActionItem
objects, so by the time your render()
function receives its ActionItemCollection
argument, it "knows" each element in the collection is definitely an ActionItem
.
That said, that's perhaps an awful lot of work when you could just get render()
to check if the element is legit, and throw an exception if not. It's not a perfect solution, but CF is creating an imperfect situation, so fair enough.
Upvotes: 4