Coldfusion能在函数参数中定义数组类型吗?

4

在 ColdFusion 组件内,我这样声明一个函数:

string function render(required Array actions) output=false {
//...
}

因此,函数参数只能接受数组。但是,我需要确保数组仅包含“ActionItem”对象(有一个ActionItem.cfc组件)。

ColdFusion中是否有一种方法来对数组内容进行类型提示?在这种情况下,您建议采用什么解决方案?


1
CFML没有类型化数组。如果您确实需要确保这一点,则需要在循环内使用isInstanceOf(但您可能实际上并不需要)。 - Peter Boughton
请注意,您在脚本中不需要使用 output=false - 除非您明确使用 writeOutput/writeDump 等输出内容,否则它不会输出任何内容。 - Peter Boughton
为什么你不把它标记为“答案”,@PeterBoughton?毕竟它就是答案... - Adam Cameron
1
你可以创建一个 ArrayCollection 的 CFC,然后可能会扩展它到 ActionItemCollection,这样你就可以在集合上进行类型提示。 - AlexP
1
哇,@AlexP...太巧了(因为在你发表评论的同时我正在打我的答案!)。 - Adam Cameron
显示剩余4条评论
4个回答

4
为了解释我的评论,下面是你可以创建的可能集合的概要。
我喜欢集合类,这里的ArrayCollection类非常可重用,并且允许您将包装的数组作为对象使用。
    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) 
        {

        }

    }

在某些情况下可能有些过度,但它允许您强制执行数组中的项目类型!


4
简而言之,正如Peter在评论中所说的那样,基本答案是“你不能”。 ColdFusion没有类型数组的概念。
有两种方法可以解决这个问题。首先是强制验证每个数组项,确保它是所需的类型。这就是Peter建议的,通常也是我会做的事情。
如果不行,您可以实现一个ActionItemCollection.cfc,其中包含ActionItems数组,并让ActionItemCollection.cfc仅接受ActionItem对象,因此当您的render()函数接收到其ActionItemCollection参数时,“知道”集合中的每个元素绝对是ActionItem
话虽如此,当您可以使render()检查元素是否合法并在不合法时抛出异常时,这可能需要大量工作。这不是完美的解决方案,但CF正在创建一个不完美的情况,所以还算公平。

我使用了实现Collection组件的解决方案。在我看来,这个答案是最全面的,尽管其他答案也是正确的且是好的解决方案! - Philipp

3
实际上,ColdFusion对数组类型的验证有一些支持(不要与类型化数组混淆),但它只适用于自定义组件,对于原始类型并不起作用。然而,我还没有找到除了这篇博客文章之外的其他关于此功能的文档。
假设我们有一个名为SomeObject的组件。
我们可以这样写:
<cffunction name="testArrayTypeValidation">
    <cfargument name="someObjects" type="SomeObject[]" required="yes">

    <cfdump var="#someObjects#">
</cffunction>

接着像这样调用我们的函数:

<cfset testArrayTypeValidation([new SomeObject()])>

然而,需要注意的是它只会验证数组中第一个项目的类型,这意味着以下内容也可以正常工作:

 <cfset testArrayTypeValidation([new SomeObject(), 'some string'])>

此外,它似乎不能用于原始类型,因此您不能使用例如type="string[]",这有点令人失望。
对于原始类型,您将不得不实现自己的具体包装类,以确保仅包含某种类型的原语,并将该类用作参数类型。

0
你可以编写一个函数来检查数组。它需要2个参数,要检查的数组和对象类型,并返回布尔值。该函数将循环遍历该对象并确定该索引处的值是否为对象,如果是,则查看其元数据以确定它是否是所需类型。第一次发现错误元素时,设置false返回值并中止循环。这不是最理想的解决方案,但它可以工作,并且通用,您可以在任何其他组件中使用它作为检查。
此外,出于您自己的理智考虑,我肯定会按您希望的方式引用所有内容: public model.bean.Foo[] function Read(required model.bean.Foo aBean) {...}
因此,该函数需要一个Foo对象作为参数,并返回一个Foo对象的数组。只需确保将映射添加到初始路径点(在我的情况下为“model”),以便CF知道从哪里开始查找它。在Application.cfc中,您需要添加类似以下内容的内容:
this.mappings ["/ model"] = getDirectoryFromPath(expandPath(“。”))&“myProjectDir / model”;

虽然这与原问题无关,但我喜欢使用清晰的引用的评论! - Philipp

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接