在AS3中设置对象属性的默认值

时间:2010-12-28 20:52:03

标签: actionscript-3

我是一个动作新手所以请耐心等待我。下面是一个函数,我很好奇如何为循环中创建的对象设置默认属性值。

在下面的示例中,这些属性对于在循环中创建的每个对象都是相同的:titleTextField.selectable,titleTextField.wordWrap,titleTextField.x

如果将这些属性拉出循环,它们将为null,因为尚未创建TextField对象,但每次都必须设置它们似乎很愚蠢。这样做的正确方法是什么。谢谢!

var titleTextFormat:TextFormat = new TextFormat();   
    titleTextFormat.size = 10;  
    titleTextFormat.font = "Arial";
    titleTextFormat.color = 0xfff200;

for (var i=0; i<arrThumbPicList.length; i++) {

    var yPos = 55 * i

    var titleTextField:TextField = new TextField();  
        titleTextField.selectable = false;
        titleTextField.wordWrap = true;
        titleTextField.text = arrThumbTitles[i];
        titleTextField.x = 106;
        titleTextField.y = 331 + yPos;

    container.addChild(titleTextField);
    titleTextField.setTextFormat(titleTextFormat);

}

4 个答案:

答案 0 :(得分:3)

这里基本上有三种选择。

  1. 您可以创建一个自定义类 充当TextFormat的代理。 例如,TextFormatProxy,其中 可以在其中创建一个TextFormat 构造函数并设置每个 默认值。见this link 或谷歌“AS3代理模式。”
  2. 您可以编写一个自定义类 扩展TextFormat,同样,设置 这些默认值 构造函数,或在函数中 你的选择。
  3. 你可以使用一个小帮手 像这样的功能

  4. package {
        import flash.display.Sprite;
    
        public class DefaultProperties extends Sprite{
    
            public var s:Sprite;
    
            public function DefaultProperties() {
                s = new Sprite();
                s.graphics.beginFill(0x00ff00, 1);
                s.graphics.drawRect(0, 0, 100, 100);
                s.graphics.endFill();
                this.setDefaults(s, {x:100, y:200, scaleX:.5});
                this.addChild(s);
           }
    
           function setDefaults($obj:*, $properties:Object):void {
               for (var i in $properties) {
                   $obj[i] = $properties[i];
               }
           }
        }
    }
    

答案 1 :(得分:2)

在不知道周围代码的情况下,我建议将任何构造逻辑放在工厂对象中。如果这太过分了,那么我会说你的代码没问题。将它拉出循环并进入辅助方法实际上只是添加了另一层间接,这不仅难以读取,而且由于您在堆栈上引入了另一个方法调用,因此效率也较低。

如果您的类对事物的创建方式并不感兴趣,而只需要一个或多个实例,那么使用工厂对象是很好的。这样,工厂负责创建对象,并且您可以很好地分离关注点。

我不建议创建仅用于设置实例属性的代理结构。我认为这是一种反模式,因为它有利于继承而不是组合,它只是为了代码重用的目的。但这样做意味着你将自己锁定在特定的实现上,这可能不是你想要的。仅仅因为你的textfield 具有某个值,并不意味着 是一个不同的类型。

这是您的代码在使用工厂模式时的外观,首先是格式工厂:

public interface FormatFactory
{
    function getInstance():TextFormat;
}

public class TitleFormatFactory implements FormatFactory
{
    public function getInstance():TextFormat
    {
        var format:TextFormat = new TextFormat();   
            format.size = 10;  
            format.font = "Arial";
            format.color = 0xfff200;

        return format;
    }
}

工厂可能参数化也可能不参数化:

public interface TextFieldFactory
{
    function getInstance(text:String, position:Point, format:TextFormat):TextField;
}

public class TitleFactory implements TextFieldFactory
{
    public function getInstance(text:String, position:Point, format:TextFormat):TextField
    {
        var title:TextField = new TextField();  
            title.selectable = false;
            title.wordWrap = true;
            title.text = text;
            title.x = position.x;
            title.y = position.y;
            title.setTextFormat(format);

        return title;
    }
}

最后,这就是您使用代码的方式:

var formatFactory:FormatFactory = new TitleFormatFactory();
var titleFactory:TextFieldFactory = new TitleFactory();

var format:TextFormat = formatFactory.getInstance();

for (var i = 0; i < arrThumbPicList.length; i++)
{
    var position:Point = new Point(106, 331 + 55 * i);
    var title:TextField = titleFactory.getInstance(text, position, format);

    container.addChild(title);
}

除了可读性之外,一个巨大的好处是你现在可以交换工厂的实现,从而改变你正在使用的组件类型,而不必改变你的实际逻辑。您所要做的就是更改对工厂的引用。

此外,通过分离问题,您可以更轻松地专注于代码的某个方面,从而减少引入错误的风险,如果您仍然这样做,那么通常更容易发现和修复。此外,当您分离关注点,更重要的是,从业务逻辑中创建逻辑时,单元测试代码要容易得多。

答案 2 :(得分:0)

如果我接近同样的问题,我会使用与你发布的相同的问题,因为制作新的数据结构是不必要的。另一种方法是创建一个接受文本框作为参数的函数:

for (var i=0; i<arrThumbPicList.length; i++) {
     var titleTextField:TextField = new TextField();
     setProperties(titleTextField,i);
}


function setProperties(txt:TextField,offset:int){
       var yPos = 55 * offset;
       txt.selectable = false;
       txt.wordWrap = true;
       txt.text = arrThumbTitles[offset];
       txt.x = 106;
       txt.y = 331 + yPos;

       container.addChild(titleTextField);
       titleTextField.setTextFormat(titleTextFormat);

       i++;
  }

虽然我可能会按照您发布的方式进行操作,除非您从多个for循环中添加内容。

答案 3 :(得分:0)

您的代码对我来说没问题。简单有效。你只有3个固定参数,对我来说没有必要做更多的事情:

titleTextField.selectable = false;
titleTextField.wordWrap = true;
titleTextField.x = 106;

与其他答案不同,我会做一个辅助函数来获取带有所有固定参数的文本字段(如果有很多事情要做,我会这样做。)

function createMyContextTextField():TextField{
    textfield:TextField = new textField();
    textfield.selectable = false;
    textfield.wordWrap = true;
    textfield.x = 106;
    return textfield;
}