Как эмулировать аргументы ключевых слов в функциях ActionScript 3 - PullRequest
7 голосов
/ 04 января 2009

Функции в Python можно вызывать с помощью аргументов ключевого слова в форме: ключевое слово = значение. Например, следующая функция:

def parrot(voltage, state='a stiff', action='voom', type='Norwegian Blue'):
    print "-- This parrot wouldn't", action,
    print "if you put", voltage, "volts through it."
    print "-- Lovely plumage, the", type
    print "-- It's", state, "!"

можно вызвать любым из следующих способов:

parrot(1000)
    parrot(action = 'VOOOOOM', voltage = 1000000)
    parrot('a thousand', state = 'pushing up the daisies')
    parrot('a million', 'bereft of life', 'jump')

ActionScript 3 не имеет этой возможности. Как мне лучше всего подражать?

Ответы [ 4 ]

7 голосов
/ 04 января 2009

Это не выдаст никаких ошибок во время компиляции, если вы ошибетесь, но вы можете сделать что-то вроде этого:

public function awesomefunction(input:Object):void {
    if (input.foo) trace("got foo");
    if (input.bar) trace("got bar");
}

А потом при вызове это делается так:

awesomefunction( { foo : 23, bar : 99 } );

Скобки {} создают встроенный объект. Длинная версия приведенного выше кода может быть написана так:

var obj:Object = new Object();
obj.foo = 23;
obj.bar = 99;
awesomefunction( obj );

Если вместо этого указать массив:

awesomefunction( [23, 99 ] );

([] это сокращение для массива между прочим)

Индексы будут доступны так:

public function awesomefunction(input:Object):void {
    if (input[0]) trace("got foo");
    if (input[1]) trace("got bar");
}

Итак, чтобы объединить все это, вы можете использовать тот факт, что || Оператор возвращает значение объекта, который сначала оценивается как true, а не просто true , чтобы сделать:

public function awesomefunction(input:Object):void {
    var foo:int = input.foo || input[0];
    var bar:int = input.bar || input[1];
    if (foo) trace("got foo:", foo);
    if (bar) trace("got bar:", bar);
}

Итак, вышеприведенная функция выдаст одинаковый вывод для всех этих трех вызовов:

awesomefunction( { foo : 23, bar :55 } );
awesomefunction( { bar : 55, foo : 23 } );
awesomefunction( [ 23, 55 ] );

Это, однако, не позволит вам смешивать именованные и нумерованные, но вы можете сделать так:

awesomefunction( { foo : 23, 1 : 55 } );

Это не очень красиво, но работает!

4 голосов
/ 06 января 2009

Краткий ответ: в Actionscript порядок параметров является частью сигнатуры функции. Чтобы обойти этот факт, вам нужно либо проделать дополнительную работу, либо потакать плохим практикам кодирования, которые укусят вас позже. Я бы сказал, что у вас есть два «хороших» варианта для достижения гибкости, аналогичной тому, что вы ищете. Формальным способом было бы определить класс данных, который будет действовать как параметр функции. То есть:

public class ComplaintData {
    public var state:String = "a stiff";
    public var action:String = "voom";
    public var type:String = "Norwegian Blue";
    public var voltage:String;

    public function ComplaintData( v:String ) {
        voltage = v;
    }
}

// somewhere else....

function parrot( cd:ComplaintData ) {
    trace "-- This parrot wouldn't " + cd.action;
    // etc.
}

var cd:ComplaintData = new ComplaintData( "a million" );
cd.action = "jump";
parrot( cd );

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

function parrot( voltage:String, 
                 state:String=null, 
                 action:String=null, 
                 type:String=null)  {
    if (state==null) { state = 'a stiff'; }
    if (action==null) { action = 'voom'; }
    if (type==null) { type = 'Norwegian Blue'; }
    // ....
}
parrot('1000')
parrot('1000000', null, 'jump')

Но если оба эти варианта кажутся громоздкими, это потому, что они есть. В конечном счете, я думаю, что в конечном счете лучше всего усвоить идею, что упорядоченные списки параметров являются частью грамматики Actionscript, и вам, вероятно, лучше не пытаться их избегать. Это приводит либо к потере простоты (как указано выше), либо приводит к плохим практикам (например, использование неструктурированных объектов для параметров, как предлагается в других ответах, что жертвует многими преимуществами проверки типов и ошибок).

Наиболее сбалансированный способ работы с грамматикой - просто использовать необязательные параметры, когда это возможно, таким образом:

function parrot( voltage:String, 
                 state:String='a stiff', 
                 action:String='voom', 
                 type:String='Norwegian Blue')  {
    // ...
}
parrot('1000');
parrot('1000000', 'pushing up the daisies');
parrot('a million', 'bereft of life', 'jump')

Вы все еще должны смириться с тем фактом, что только конечные параметры могут быть опущены, но именно так создается язык (и как определяются и используются его нативные методы).

1 голос
/ 04 января 2009

В actionScript 3.0 существует специальный тип, называемый ... (rest) . Поместите этот тип в список параметров для функции, и тогда эта функция сможет принимать любое количество аргументов. Правильный sytanx: ... arrayName , где arrayName - имя массива, который будет содержать аргументы.

public function forYou( ...args ) : void{
   for(var i : int = 0; i 
0 голосов
/ 04 января 2009

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

...