Передача Vector. <T>ссылки как объекта, приведение вызывает создание копии - PullRequest
0 голосов
/ 10 марта 2011

Я хотел бы иметь возможность передать Векторы вокруг в качестве ссылок . Теперь, если метод принимает Vector.<Object>, тогда передача Vector.<TRecord>, где TRecord наследует непосредственно от Object, не работает. Где метод просто берет Object ; скажем vec: Object, тогда прохождение вектора возможно. Оказавшись внутри этого метода, явное приведение на некотором этапе требуется для получения доступа к vec в качестве вектора. К сожалению, приведение, кажется, делает копию, что означает, что завершение одного в нескольких Flex ListCollectionViews бесполезно; каждый ListCollectionView будет указывать на свой вектор.

Использование массивов с ArrayCollection не представляет такой проблемы, но я упускаю из виду безопасность типов, аккуратность (код должен быть достаточно чистым, чтобы их можно было съесть) и преимущества производительности Vector.

Есть ли способ разыграть их или передать их как ссылки в общем виде без копирования по ходу дела?

Обратите внимание, что в этом примере IRecord является интерфейсом со свойствами {r / w id: int & name: String}, но это может быть класс, скажем TRecord {id: int; name: String} или любой другой используемый тип.

protected function check(srcVec: Object): void
{
  if (!srcVec) {
    trace("srcVec is null!");
    return;
  }
  // srcVec = (@b347e21)
  trace(srcVec.length); // 4, as expected
  var refVec: Vector.<Object> = Vector.<Object>(srcVec);
  // refVec = (@bc781f1)
  trace(refVec.length); // 4, ok, but refVec has a different address than srcVec
  refVec.pop();
  trace(refVec.length); // 3 ok
  trace(srcVec.length); // 4 - A copy was clearly created!!!
}

protected function test(): void
{
  var vt1: Vector.<IRecord> = new Vector.<IRecord>;  // (@b347e21) - original Vector address
  var vt2: Vector.<Object> = Vector.<Object>(vt1);   // (@bbb57c1) - wrong
  var vt3: Vector.<Object> = vt1 as Vector.<Object>; // (@null)    - failure to cast
  var vt4: Object = vt1;                             // (@b347e21) - good
  for (var ix: int = 0; ix < 4; ix++)
    vt1.push(new TRecord);
  if (vt1) trace(vt1.length); // 4, as expected
  if (vt2) trace(vt2.length); // 0
  if (vt3) trace(vt3.length); // vt3 is null
  if (vt4) trace(vt4.length); // 4
  if (vt1) trace(Vector.<Object>(vt1).length); // 
  trace("calling check(vt1)");
  check(vt1);
}

1 Ответ

4 голосов
/ 10 марта 2011

Это невозможно.Если тип T ковариантен с типом U, то любой контейнер T не ковариантен с контейнером типа U. C #, и Java сделал это со встроенными типами массивов, и их разработчики хотели бы вернуться и вырезать его,

Рассмотрим, если этот код был допустим

var vt1: Vector.<IRecord> = new Vector.<IRecord>;  
var vt3: Vector.<Object> = vt1 as Vector.<Object>; 

Теперь у нас есть Vector.<Object>.Но подождите - если у нас есть контейнер с объектами, тогда, конечно, мы можем вставить в него объект - верно?

vt3.push(new Object());

Но подождите - потому что на самом деле это экземпляр Vector.<IRecord>, вы не можете сделатьэто, хотя контракт Vector.<Object> ясно говорит, что вы можете вставить Object.Вот почему такое поведение явно недопустимо.

Редактировать: Конечно, ваш фреймворк может позволить ему стать неизменяемой ссылкой на такое, что равно безопасный.Но у меня мало опыта с ActionScript, и я не могу убедиться, что он действительно есть.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...