как да инициализирате масив до даден размер в haxe

Чудех се дали има начин да се инициализира масив до даден размер n (като в std::vector конструктора на c++ или отговора на @steve richey по-долу без хакването на елемента hint)?

Мисълта ми беше да върна n елемента по подразбиране в новосъздадения масив, но дори това изглежда невъзможно, защото изглежда няма начин да се дефинира елемент по подразбиране, както е показано в първоначалния въпрос по-долу:

-- оригинален въпрос --

Опитвам се да напиша статична функция в haxe (от 3.0.1), за да създам масив с даден размер n, съдържащ типове от произволен тип T. Не можах да разбера как да използвам Type.createEmptyInstance() правилно за това. Най-близкото, което мога да получа, е:

class Main {
    static public function new_array<T>(n:Int):Array<T> {
    var a:Array<T> = new Array<T>();
    var t:T = new T(); //not OK
    for (i in 0...n)
        a.push(Type.createEmptyInstance(Type.getClass(t)));
    return a;
}
    static public function main() {
            var a:Array<Int> = new_array(3);
    }
}

Вторият ред в new_array() е проблематичен. Компилаторът казва: Main.hx:4: characters 12-19 : Only generic type parameters can be constructed.

Въпросът ми е как да накарам такава функция да работи за масив от произволен тип T.

Благодаря,


person tinlyx    schedule 24.12.2013    source източник


Отговори (3)


В Haxe масивите не са с фиксирана дължина. Вместо това можете да използвате вектори, които се държат по подобен начин, но имат фиксирана дължина.

class Test {
    static function main(){
        var vector = new haxe.ds.Vector(5); // Starting Length
        vector[0] = "zero";
        vector[3] = "three";
        // vector[7] = "seven"; // Will cause Runtime error on some platforms! 
        for ( val in vector ) {
            trace( val );
            // "zero"
            // null
            // null
            // "three"
            // null
        }
    }
}

Моля, обърнете внимание, че векторите са "абстракти", така че те обгръщат основен тип. На някои платформи (напр. Flash) това е истински вектор и ще генерира грешки за достъп извън границите. На други платформи (напр. JS) основната имплементация е масив, така че може да не изведе грешка за извличане на елемент извън границите и т.н. Ако се придържате към ненарушена разумна употреба, трябва да сте добре :)

Като странична бележка относно масивите, ако направите нещо като:

var arr = [];
arr[0] = "zero";
arr[8] = "eight";

Някои платформи ще добавят елементи 1-7 с "null", а някои няма - поведението зависи от платформата и не е надеждно.

Вижте:

person Jason O'Neil    schedule 25.12.2013
comment
Благодаря много за отговора. Но трябва да накарам тази работа за Array‹T›, защото трябва да добавя елементи към контейнера. Също така, това, от което се нуждаех за Array‹T›, както е описано по-горе, е по-скоро функцията C++ vector‹›.resize(), която може да се използва за инициализиране или преразпределяне на хранилище за C++ масив. - person tinlyx; 27.12.2013

Ето, опитайте това:

@:generic static public function new_Array<T>( ArrayType:T, Length:Int ):Array<T> {
    var empty:Null<T> = null;
    var newArray:Array<T> = new Array<T>();

    for ( i in 0...Length ) {
        newArray.push( empty );
    }

    return newArray;
}

След това, когато искате да създадете нов масив:

var myArray:Array<Int> = new_Array( 1, 25 );

Вярно е, че използването на 1 за сигнализиране, че типът трябва да бъде Int е малко хак и някой друг може да знае по-добър начин, но се надяваме, че това помага.

person steve richey    schedule 29.12.2013

ето един лесен начин, ако трябва да зададете дължината на масива, дори ако той няма данни в него:

    var myArray:Array<String> = new Array<String>();   //in this case array of strings
    myArray[5] = null;                                 //in this case setting length to 6

елементи 0 - 4 не се задават (ако дебъгвате, те не са в списъка), но ще бъдат третирани като нулеви.

person Misiek    schedule 11.01.2016