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));
}
}