Чтобы передать его в функцию, мне нужно, чтобы это был какой-то дочерний тип (который я знаю заранее, что все элементы гарантированно будут иметь этот дочерний тип).
Если выдействительно уверены, что это так, это безопасно использовать 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
.
В конце дня этоКомпромисс между затратами на производительность создания копии (которые могут быть незначительными в зависимости от размера) и тем, насколько вы уверены, что вы умнее компилятора / знаете обо всех существующих ссылках.