Array sınıfı, son olmayan birkaç çekirdek sınıftan biridir, başka bir deyişle, kendi Array alt sınıflarınızı oluşturabilirsiniz. Bu bölüm, Array alt sınıfının nasıl oluşturulacağını gösteren bir örnek sağlar ve işlem sırasında ortaya çıkabilecek bazı sorunları ele alır.
Önceden de belirtildiği gibi, ActionScript'teki diziler türlenmiş değildir ancak yalnızca belirli bir veri türündeki öğeleri kabul eden bir Array alt sınıfı oluşturabilirsiniz. Aşağıdaki bölümlerde verilen örnek, öğelerini birinci parametrede belirtilen veri türünün değerleriyle sınırlandıran TypedArray adında bir Array alt sınıfını tanımlar. TypedArray sınıfı yalnızca Array sınıfının nasıl genişletildiğini gösteren bir örnek olarak sunulmuş olup birçok nedenden dolayı üretim amaçları için uygun olmayabilir. İlk olarak, tür denetleme, derleme zamanında değil çalışma zamanında gerçekleşir. İkinci olarak, yöntemler istisna atacak şekilde kolayca değiştirilebilse de, TypedArray yöntemi bir uyuşmazlıkla karşılaştığında uyuşmazlık yoksayılır ve herhangi bir istisna atılmaz. Üçüncü olarak, sınıf, herhangi bir türdeki değerleri diziye eklemek için dizi erişimi operatörünün kullanılmasını önleyemez. Dördüncü olarak, kodlama stili, basitliği performans en iyileştirmesinden daha üstün tutar.
Not: Türlenmiş dizi oluşturmak için burada açıklanan tekniği kullanabilirsiniz. Ancak, Vector nesnesinin kullanılması daha iyi bir yaklaşım olacaktır. Vector örneği gerçek bir türlenmiş dizi olup Array sınıfına veya herhangi bir alt sınıfa göre daha yüksek performans ve iyileştirmeler sağlar. Bu açıklamanın amacı, Array alt sınıfının nasıl oluşturulduğunu göstermektir.
Alt sınıfı bildirme
Sınıfın bir Array alt sınıfı olduğunu belirtmek için extends anahtar sözcüğünü kullanın. Array alt sınıfının, Array sınıfı gibi dynamic niteliğini kullanması gerekir. Aksi takdirde, alt sınıfınız düzgün çalışmaz.
Aşağıdaki kod, veri türünü barındıran bir sabiti, yapıcı yöntemini ve diziye öğe ekleyebilen dört yöntemi içeren TypedArray sınıfının tanımını gösterir. Her yöntemin kodu bu örnekte çıkarılmıştır ancak ilerleyen bölümlerde ele alınıp kapsamlı şekilde açıklanacaktır:
public dynamic class TypedArray extends Array
{
private const dataType:Class;
public function TypedArray(...args) {}
AS3 override function concat(...args):Array {}
AS3 override function push(...args):uint {}
AS3 override function splice(...args) {}
AS3 override function unshift(...args):uint {}
}
Bu örnek, -as3 derleyici seçeneğinin true değerine ve -es derleyici seçeneğinin false değerine ayarlandığını varsaydığından, geçersiz kılınan dört yöntem de public niteliği yerine AS3 ad alanını kullanır. Adobe Flash Builder ve Adobe® Flash® Professional için varsayılan ayarlar bunlardır.
Prototip miras kullanmayı tercih eden ileri düzey bir geliştiriciyseniz,
-es derleyici seçeneği
true değerine ayarlanmış şekilde TypedArray sınıfını derlemek için bu sınıf üzerinde iki küçük değişiklik yapabilirsiniz. İlk olarak, tüm
override niteliklerini kaldırın ve AS3 ad alanını
public niteliğiyle değiştirin. İkinci olarak,
Array.prototype öğesini dört
super öğesinin yerine yedek olarak kullanın.
TypedArray yapıcısı
Yapıcının rastgele uzunluktaki argümanlar listesini kabul etmesi gerektiğinden, alt sınıf yapıcısı ilginç bir zorluk ortaya çıkarır. Dizi oluşturmak için argümanların üst yapıcıya iletilme şekli zorluk yaratır. Argümanlar listesini dizi olarak iletirseniz, üst yapıcı bunu Array türünde tek bir argüman olarak değerlendirir ve sonuçta elde edilen sizi her zaman 1 öğe uzunluktadır. Doğrudan geçiş argümanı listeleri, geleneksel olarak Function.apply() yöntemi kullanılarak işlenir. Bu yöntem, argümanlar dizisini ikinci parametre olarak alır ancak işlevi çalıştırırken bunu bir argümanlar dizisine dönüştürür. Ne yazık ki, Function.apply() yöntemi yapıcılarla kullanılamaz.
Kalan tek seçenek, TypedArray yapıcısında Array yapıcısının mantığını yeniden oluşturmaktır. Aşağıdaki kod, Array sınıfı yapıcısında kullanılan algoritmayı gösterir; bu algoritmayı Array alt sınıfı yapıcınızda yeniden kullanabilirsiniz:
public dynamic class Array
{
public function Array(...args)
{
var n:uint = args.length
if (n == 1 && (args[0] is Number))
{
var dlen:Number = args[0];
var ulen:uint = dlen;
if (ulen != dlen)
{
throw new RangeError("Array index is not a 32-bit unsigned integer ("+dlen+")");
}
length = ulen;
}
else
{
length = n;
for (var i:int=0; i < n; i++)
{
this[i] = args[i]
}
}
}
}
TypedArray yapıcısı, kod üzerinde yalnızca dört değişiklikle Array yapıcısındaki kodun büyük bir kısmını paylaşır. İlk olarak parametre listesi, dizinin veri türünün belirtimine olanak sağlayan yeni bir gerekli Class türü parametresini içerir. İkinci olarak, yapıcıya iletilen veri türü, dataType değişkenine atanır. Üçüncü olarak, else deyiminde, for döngüsünden sonra length özelliğinin değeri atanır, böylece length yalnızca uygun türdeki argümanları içerir. Dördüncü olarak, for döngüsünün gövdesi push() yönteminin geçersiz kılınmış sürümünü kullanır, böylece yalnızca doğru veri türündeki argümanlar diziye eklenir. Aşağıdaki örnek, TypedArray yapıcı işlevini gösterir:
public dynamic class TypedArray extends Array
{
private var dataType:Class;
public function TypedArray(typeParam:Class, ...args)
{
dataType = typeParam;
var n:uint = args.length
if (n == 1 && (args[0] is Number))
{
var dlen:Number = args[0];
var ulen:uint = dlen
if (ulen != dlen)
{
throw new RangeError("Array index is not a 32-bit unsigned integer ("+dlen+")")
}
length = ulen;
}
else
{
for (var i:int=0; i < n; i++)
{
// type check done in push()
this.push(args[i])
}
length = this.length;
}
}
}
TypedArray geçersiz kılınmış yöntemler
TypedArray sınıfı, bir diziye öğe ekleyebilen Array sınıfının dört yöntemini geçersiz kılar. Her durumda, geçersiz kılınan yöntem, doğru veri türünde olmayan öğelerin eklenmesini önleyen bir tür denetimi ekler. Sonra da her yöntem kendisinin üst sınıf sürümünü çağırır.
push() yöntemi bir for..in döngüsüyle argümanlar listesini yineler ve her argümanda tür denetimi gerçekleştirir. Doğru veri türünde olmayan tüm argümanlar, splice() yöntemiyle args dizisinden kaldırılır. for..in döngüsü sona erdikten sonra, args dizisi yalnızca dataType türündeki değerleri içerir. Daha sonra, aşağıdaki kodun gösterdiği gibi, güncellenmiş args dizisiyle push() öğesinin üst sınıf sürümü çağrılır:
AS3 override function push(...args):uint
{
for (var i:* in args)
{
if (!(args[i] is dataType))
{
args.splice(i,1);
}
}
return (super.push.apply(this, args));
}
concat() yöntemi, tür denetiminden geçen argümanları saklamak için passArgs adında geçici bir TypedArray oluşturur. Bu, push() yönteminde bulunan tür denetimi kodunun yeniden kullanılmasına olanak sağlar. for..in döngüsü, args dizisini yineler ve her argümanda push() öğesini çağırır. passArgs öğesi TypedArray olarak yazılmış olduğundan, push() öğesinin TypedArray sürümü çalıştırılır. Daha sonra concat() yöntemi, aşağıdaki kodun gösterdiği gibi, kendi üst sınıf sürümünü çağırır:
AS3 override function concat(...args):Array
{
var passArgs:TypedArray = new TypedArray(dataType);
for (var i:* in args)
{
// type check done in push()
passArgs.push(args[i]);
}
return (super.concat.apply(this, passArgs));
}
splice() yöntemi, argümanların rastgele bir listesini alır ancak ilk iki argüman her zaman bir dizin sayısını ve silinecek öğe sayısını ifade eder. Geçersiz kılınmış splice() yönteminin yalnızca dizin konumu 2 veya daha yukarısındaki args dizi öğeleri için tür denetimi yapmasının nedeni de budur. Koddaki ilgi çekici bir nokta da, for döngüsü içinde splice() öğesine yinelemeli çağrı yapıldığı halde, args öğesi TypedArray değil de Array türünde olduğundan, başka bir deyişle, args.splice() öğesine yapılan çağrı, yöntemin üst sınıf sürümüne yapılan bir çağrı olduğundan, bunun yinelemeli bir çağrı olmamasıdır. for..in döngüsü tamamlandıktan sonra, aşağıdaki kodda gösterildiği gibi, args dizisi yalnızca 2 veya daha yüksek dizin konumlarındaki doğru türdeki değerleri içerir ve splice() öğesi kendi üst sınıf sürümünü çağırır:
AS3 override function splice(...args):*
{
if (args.length > 2)
{
for (var i:int=2; i< args.length; i++)
{
if (!(args[i] is dataType))
{
args.splice(i,1);
}
}
}
return (super.splice.apply(this, args));
}
Dizinin başına öğe ekleyen unshift() yöntemi de argümanların rastgele bir listesini kabul eder. Geçersiz kılınmış unshift() yöntemi, aşağıdaki örnek kodda gösterildiği gibi, push() yönteminin kullandığına benzer bir algoritma kullanır:
AS3 override function unshift(...args):uint
{
for (var i:* in args)
{
if (!(args[i] is dataType))
{
args.splice(i,1);
}
}
return (super.unshift.apply(this, args));
}
}