Как преобразовать Haxe Array / Vector в другой тип - PullRequest
2 голосов
/ 16 апреля 2019

Допустим, у меня есть массив или вектор некоторого родительского типа. Чтобы передать его в функцию, мне нужно, чтобы это был какой-то дочерний тип (который я знаю заранее, что все элементы гарантированно будут всем этим дочерним типом). Есть ли удобный способ сделать это? Сейчас я могу думать только о создании нового массива.

Кроме того, похоже, что он не позволит мне сделать это наоборот: он не примет массив дочернего типа вместо родительского типа. Есть ли хороший способ решить эту ситуацию?

Похоже, cast v работает, но это предпочтительный способ?

1 Ответ

6 голосов
/ 16 апреля 2019

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

Если выдействительно уверены, что это так, это безопасно использовать cast.Я не думаю, что есть какой-нибудь более красивый способ сделать это, , и не должно быть , поскольку это по своей природе не красиво.Необходимость делать это часто указывает на недостаток дизайна в вашем коде или используемом API.


В обратном случае полезно понять , почему небезопасно.Причина не обязательно настолько интуитивна из-за этого мыслительного процесса:

Я могу назначить Child на Base, так почему я не могу присвоить Array<Child> на Array<Base>?

Этот точный пример используется для объяснения Дисперсия в Руководстве по Haxe .Вы, безусловно, должны прочитать его полностью, но я дам краткое резюме здесь:

var children = [new Child()];
var bases:Array<Base> = cast children;
bases.push(new OtherChild());

children[1].childMethod(); // runtime crash

Если бы вы могли присвоить Array<Child> для Array<Base>, , вы могли бы тогда push()типы, несовместимые с Child, .Но опять же, как вы упомянули, вы можете просто cast отключить компилятор, как в приведенном выше фрагменте кода.

Однако , это не всегда безопасно - возможно, код еще естьсодержит ссылку на этот оригинал Array<Child>, который теперь внезапно содержит вещи, которых он не ожидает!Это означает, что мы можем сделать что-то вроде вызова childMethod() для объекта, у которого нет этого метода, и вызвать сбой во время выполнения.

Обратное также верно, если нет кода, удерживающего такую ​​ссылку (или если ссылки доступны только для чтения, например, через haxe.ds.ReadOnlyArray), можно использовать cast.


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

...