ActionScript OOP desteğinin geçmişi
ActionScript 3.0, önceki ActionScript sürümleri esas alınarak oluşturulduğundan, ActionScript nesne modelinin nasıl geliştiğinin anlaşılması yardımcı olabilir. ActionScript, önceki Flash Professional sürümleri için basit bir komut dosyası yazma mekanizması olarak kullanılmaya başlamıştır. Daha sonra programcılar ActionScript ile gittikçe daha karmaşık uygulamalar oluşturmaya başladı. Bu programcıların gereksinimlerine yanıt vermek için, sonraki her sürüme, karmaşık uygulamaların oluşturulmasını kolaylaştıran dil özellikleri eklendi.
ActionScript 1.0
ActionScript 1.0, Flash Player 6 ve öncesinde kullanılan dil sürümüdür. Bu geliştirme aşamasında bile ActionScript nesne modeli, temel veri türü olarak nesne kavramını esas almıştı. ActionScript nesnesi bir grup
özellik
içeren birleşik bir veri türüdür. Nesne modeli ele alınırken
özellik
terimi, değişkenler, işlevler veya yöntemler gibi bir nesneye eklenen her şeyi içerir.
Bu birinci nesil ActionScript,
class
anahtar sözcüğüyle sınıfların tanımlanmasını desteklemese de, prototip nesne adı verilen özel bir nesne türünü kullanarak bir sınıfı tanımlayabilirsiniz. Java ve C++ gibi sınıf tabanlı dillerde yaptığınız gibi, somut nesneler olarak başlatacağınız soyut bir sınıf tanımı oluşturmak için
class
anahtar sözcüğünü kullanmak yerine, ActionScript 1.0 gibi prototip tabanlı diller, başka nesneler için bir model (veya prototip) olarak varolan bir nesneyi kullanır. Sınıf tabanlı bir dilde nesneler, o nesnenin şablonu görevini gören bir sınıfa işaret edebilse de, prototip tabanlı bir dildeki nesneler, bunun yerine nesnenin şablonu görevini gören başka bir nesneye (prototip) işaret eder.
ActionScript 1.0'da bir sınıf oluşturmak üzere o sınıf için bir yapıcı işlevi tanımlarsınız. ActionScript'te işlevler yalnızca soyut tanımlar değil, gerçek nesnelerdir. Oluşturduğunuz yapıcı işlevi, o sınıfın örnekleri için prototip nesne görevi görür. Aşağıdaki kod, Shape adında bir sınıf oluşturur ve varsayılan olarak
true
değerine ayarlanmış
visible
adında tek bir özelliği tanımlar:
// base class
function Shape() {}
// Create a property named visible.
Shape.prototype.visible = true;
Bu yapıcı işlevi, aşağıdaki gibi
new
operatörüyle başlatabileceğiniz bir Shape sınıfını tanımlar:
myShape = new Shape();
Shape()
yapıcı işlevi nesnesi, Shape sınıfının örnekleri için prototip görevi gördüğü gibi, Shape sınıfının alt sınıfları (başka bir deyişle, Shape sınıfını genişleten diğer sınıflar) için de prototip görevi görebilir.
Shape sınıfının alt sınıfı olan bir sınıfın oluşturulması iki adımda gerçekleşir. İlk olarak, aşağıdaki gibi, sınıf için bir yapıcı işlevi tanımlayarak sınıfı oluşturun:
// child class
function Circle(id, radius)
{
this.id = id;
this.radius = radius;
}
İkinci olarak, Shape sınıfının, Circle sınıfının prototipi olduğunu bildirmek için
new
operatörünü kullanın. Varsayılan olarak, oluşturduğunuz tüm sınıflar kendi prototipi olarak Object sınıfını kullanır, başka bir deyişle,
Circle.prototype
öğesi geçerli olarak bir genel nesne (Object sınıfının bir örneği) içerir. Circle öğesinin prototipinin Object değil Shape olduğunu belirtmek için, aşağıdaki kodu kullanarak genel bir nesneyi değil, Shape nesnesini içerecek şekilde
Circle.prototype
öğesinin değerini değiştirin:
// Make Circle a subclass of Shape.
Circle.prototype = new Shape();
Şimdi Shape sınıfı ve Circle sınıfı,
prototip zinciri
olarak bilinen bir miras ilişkisiyle birbirine bağlanır. Diyagramda, bir prototip zincirindeki ilişkiler gösterilmektedir:
Her prototip zincirinin sonundaki temel sınıf, Object sınıfıdır. Object sınıfı, ActionScript 1.0'da oluşturulmuş tüm nesneler için temel prototip nesnesine işaret eden
Object.prototype
adında statik bir özellik içerir. Örnek prototip zincirimizdeki bir sonraki nesne Shape nesnesidir. Bunun nedeni,
Shape.prototype
özelliğinin asla açıkça ayarlanmaması ve bu nedenle de genel nesne (Object sınıfının bir örneği) içermeye devam etmesidir. Bu zincirdeki son halka, prototipine (Shape sınıfına) bağlı Circle sınıfıdır. (
Circle.prototype
özelliği bir Shape nesnesi içerir.)
Aşağıdaki örnekte olduğu gibi Circle sınıfının bir örneğini oluşturursanız, örnek Circle sınıfının prototip zincirini miras alır:
// Create an instance of the Circle class.
myCircle = new Circle();
Shape sınıfının bir üyesi olarak
visible
adında bir özellik içerdiğini hatırlayın. Örneğimizde,
visible
özelliği,
myCircle
nesnesinin bir parçası olarak değil, yalnızca Shape nesnesinin bir üyesi olarak bulunur ancak aşağıdaki kod satırı
true
değerini verir:
trace(myCircle.visible); // output: true
Çalışma zamanı, prototip zincirinde gezinerek
myCircle
nesnesinin
visible
özelliğini miras aldığını doğrulayabilir. Bu kodu çalıştırırken, çalışma zamanı ilk olarak
myCircle
nesnesinin özelliklerinde
visible
adındaki bir özelliği arar, ancak bu özelliği bulamaz. Daha sonra
Circle.prototype
nesnesine bakar ancak yine
visible
adındaki özelliği bulamaz. Prototip zincirinde devam ederek en sonunda
Shape.prototype
nesnesinde tanımlanmış
visible
özelliğini bulur ve o özelliğin değerini verir.
Kolaylık olması açısından, prototip zincirinin ayrıntıları ve karmaşıklığı dahil edilmemiştir. Bunun yerine amaç ActionScript 3.0 nesne modelini anlayabilmeniz için yeterli bilgiyi sağlamaktır.
ActionScript 2.0
ActionScript 2.0, Java ve C++ gibi sınıf tabanlı dillerle çalışan kişilere tanıdık gelecek şekilde sınıflar tanımlamanıza olanak sağlayan
class
,
extends
,
public
ve
private
gibi yeni anahtar sözcükler sunmuştur. ActionScript 1.0 ile ActionScript 2.0 arasında temel alınan miras mekanizmasının değişmediğinin anlaşılması önemlidir. ActionScript 2.0 yalnızca sınıfların tanımlanması için yeni bir sözdizimi eklemiştir. Prototip zinciri, her iki dil sürümünde de aynı şekilde çalışır.
Aşağıdaki alıntıda gösterildiği gibi, ActionScript 2.0 tarafından ilk defa sunulan yeni sözdizimi, birçok programcının daha sezgisel bulduğu bir şekilde sınıfları tanımlamanıza olanak sağlar:
// base class
class Shape
{
var visible:Boolean = true;
}
ActionScript 2.0'ın ayrıca derleme zamanı tür denetlemesiyle kullanılmak üzere tür ek açıklamaları da sunduğunu unutmayın. Bu, önceki örnekte bulunan
visible
özelliğinin yalnızca bir Boolean değeri içermesi gerektiğini bildirmenize olanak sağlar. Yeni
extends
anahtar sözcüğü, alt sınıf oluşturma işlemini de basitleştirir. Aşağıdaki örnekte, ActionScript 1.0'da iki adımda gerçekleştirilen işlem,
extends
anahtar sözcüğüyle tek adımda gerçekleştirilir:
// child class
class Circle extends Shape
{
var id:Number;
var radius:Number;
function Circle(id, radius)
{
this.id = id;
this.radius = radius;
}
}
Şimdi yapıcı, sınıf tanımının parçası olarak bildirilir ve
id
ve
radius
sınıf özelliklerinin de açıkça bildirilmesi gerekir.
ActionScript 2.0 ayrıca arabirimlerin tanımı için de destek eklemiştir, bu sayede nesne tabanlı programlarınızı nesneler arası iletişim için biçimsel olarak tanımlanmış protokollerle daha düzgün hale getirebilirsiniz.
ActionScript 3.0 sınıf nesnesi
Daha çok Java ve C++ ile ilişkilendirilmiş olan yaygın bir nesne tabanlı programlama paradigması, nesne türlerini tanımlamak için sınıfları kullanır. Bu paradigmayı kullanan programlama dilleri, sınıfın tanımladığı veri türü örneklerini oluşturmak için de sınıfları kullanabilir. ActionScript, sınıfları bu iki amaç için de kullanır ancak ActionScript'in prototip tabanlı bir dil olması da ilginç bir özellik katar. ActionScript, her sınıf tanımı için, hem davranışın hem de durumun paylaşılmasına olanak sağlayan özel bir sınıf nesnesi oluşturur. Ancak birçok ActionScript programcısı için bu ayrım pratik bir kodlama anlamına gelmeyebilir. ActionScript 3.0, bu özel sınıf nesnelerini kullanmadan hatta anlamadan karmaşık nesne tabanlı ActionScript uygulamaları oluşturabileceğiniz şekilde tasarlanmıştır.
Aşağıdaki diyagram, A adındaki basit bir sınıfı temsil eden bir sınıf nesnesi yapısını göstermektedir. A sınıfı,
class A {}
deyimiyle tanımlanmıştır:
Diyagramdaki her dikdörtgen bir nesneyi temsil eder. Diyagramdaki her nesne, A sınıfına ait olduğunu temsil eden bir A alt simge karakterine sahiptir. Sınıf nesnesi (CA), birçok başka önemli nesneye başvuruları içerir. Örnek nitelikleri nesnesi (TA), bir sınıf tanımı içinde tanımlanan örnek özelliklerini saklar. Sınıf nitelikleri nesnesi (TCA), dahili sınıf türünü temsil eder ve sınıf tarafından tanımlanan statik özellikleri saklar. (C alt simge karakteri "sınıfı" ifade eder.) Prototip nesnesi (PA) her zaman başlangıçta
constructor
özelliği yoluyla eklendiği sınıf nesnesini ifade eder.
Nitelikler nesnesi
ActionScript 3.0'da yeni bir özellik olan nitelikler nesnesi, performans göz önünde tutularak uygulanmıştır. Önceki ActionScript sürümlerinde, Flash prototip zincirinde dolandığı için ad arama zaman alıcı bir işlem olabiliyordu. ActionScript 3.0'da, miras alınan özellikler, üst sınıflardan alt sınıfların nitelikler nesnesine kopyalandığından, ad arama çok daha etkili olup daha az zaman alır.
Nitelikler nesnesine programcı kodu ile doğrudan erişilemez ancak performans artışı ve bellek kullanımındaki iyileşme ile bu nesnenin varlığı hissedilebilir. Nitelikler nesnesi, bir sınıfın mizanpajı ve içerikleri hakkında ayrıntılı bilgi içeren AVM2'yi sağlar. Bu bilgiler sayesinde AVM2, zaman alıcı bir işlem olan ad aramasına gerek kalmadan özelliklere erişmeye veya yöntemler çağırmaya yönelik doğrudan makine talimatları oluşturabildiğinden, çalıştırma süresini büyük ölçüde azaltabilir.
Nitelikler nesnesi sayesinde nesnenin bellek izi, önceki ActionScript sürümlerindeki benzer bir nesnenin bellek izinden çok daha küçük olabilir. Örneğin, bir sınıf mühürlenmişse (başka bir deyişle, sınıfın dinamik olduğu bildirilmemişse), o sınıfın örneği, dinamik olarak eklenmiş özelliklerin karma tablosunu gerektirmez ve nitelikler nesnelerinin işaretçilerinden ve sınıfta tanımlanmış sabit özelliklere yönelik birkaç yuvadan biraz daha fazlasını barındırabilir. Sonuç olarak, ActionScript 2.0'da 100 bayt bellek gerektiren bir nesne, ActionScript 3.0'da 20 bayt kadar düşük bellek gerektirebilir.
Not:
Nitelikler nesnesi dahili bir uygulama olup, gelecek ActionScript sürümlerinde bu uygulamanın değişmeyeceğine veya tamamen kaldırılmayacağına dair bir garanti yoktur.
Prototip nesnesi
Her ActionScript sınıf nesnesi, sınıfın prototip nesnesine başvuru niteliğinde olan
prototype
adında bir özelliğe sahiptir. Prototip nesnesi, ActionScript’in prototip tabanlı dil olması nedeniyle eski uygulamasının devamı niteliğindedir. Daha fazla bilgi için, bkz.
ActionScript OOP desteğinin geçmişi
.
prototype
özelliği salt okunur özelliktedir, başka bir deyişle, farklı nesnelere işaret edecek şekilde değiştirilemez. Bu da, prototipin farklı bir sınıfa işaret edecek şekilde yeniden atanabildiği önceki ActionScript sürümlerindeki
prototype
sınıfından farklılık gösterir.
prototype
özelliği salt okunur olsa da, bu özelliğin başvurduğu prototip nesnesi salt okunur değildir. Başka bir deyişle, prototip nesnesine yeni özellikler eklenebilir. Prototip nesnesine eklenen özellikler, sınıfın tüm örnekleri arasında paylaşılır.
Önceki ActionScript sürümlerinde tek miras mekanizması olan prototip zinciri, ActionScript 3.0'da yalnızca ikincil rol oynar. Birincil miras mekanizması olan sabit özellik mirası, nitelikler nesnesi tarafından dahili olarak işlenir. Sabit özellik, sınıf tanımının bir parçası olarak tanımlanan bir değişken veya yöntemdir. Sabit özellik mirası,
class
,
extends
ve
override
gibi anahtar sözcüklerle ilişkilendirilmiş miras mekanizması olduğundan, sınıf mirası olarak da adlandırılır.
Prototip zinciri, sabit özellik mirasından daha dinamik olan alternatif bir miras mekanizması sağlar. Yalnızca sınıf tanımının bir parçası olarak değil, aynı zamanda sınıf nesnesinin
prototype
özelliği üzerinden çalışma zamanında da sınıfın prototip nesnesine özellikler ekleyebilirsiniz. Ancak, derleyiciyi katı moda ayarlamanız durumunda,
dynamic
anahtar sözcüğüyle bir sınıf bildirmediğiniz sürece bir prototip nesnesine eklenmiş özelliklere erişemeyebileceğinizi unutmayın.
Prototip nesnesine birçok özellik eklenmiş olan sınıfa güzel bir örnek Object sınıfıdır. Object sınıfının
toString()
ve
valueOf()
yöntemleri, gerçekten Object sınıfının prototip nesnesinin özelliklerine atanmış işlevlerdir. Aşağıda, bu yöntemlerin bildirilmesinin teoride nasıl göründüğünü gösterir (uygulama ayrıntıları nedeniyle gerçek uygulama biraz daha farklıdır):
public dynamic class Object
{
prototype.toString = function()
{
// statements
};
prototype.valueOf = function()
{
// statements
};
}
Daha önceden belirtildiği gibi, sınıf tanımının dışında bir sınıfın prototip nesnesine bir özellik ekleyebilirsiniz. Örneğin,
toString()
yöntemi aşağıdaki gibi Object sınıfının dışında da tanımlanabilir:
Object.prototype.toString = function()
{
// statements
};
Ancak sabit özellik mirasının aksine, prototip mirası, bir alt sınıfta yöntemi yeniden tanımlamak istediğinizde
override
anahtar sözcüğünü gerektirmez. Örneğin, Object sınıfının bir alt sınıfında
valueOf()
yöntemini yeniden tanımlamak istiyorsanız, üç seçeneğiniz vardır. İlk olarak, sınıf tanımının içinde alt sınıfın prototip nesnesinde bir
valueOf()
yöntemini tanımlayabilirsiniz. Aşağıdaki kod, Object sınıfının Foo adında bir alt sınıfını oluşturur ve sınıf tanımının bir parçası olarak Foo alt sınıfının prototip nesnesinde
valueOf()
yöntemini yeniden tanımlar. Her sınıf Object öğesinden miras aldığı için,
extends
anahtar sözcüğünün kullanılması gerekmez.
dynamic class Foo
{
prototype.valueOf = function()
{
return "Instance of Foo";
};
}
İkinci olarak, aşağıdaki kodda gösterildiği gibi, sınıf tanımının dışında Foo alt sınıfının prototip nesnesinde bir
valueOf()
yöntemini tanımlayabilirsiniz:
Foo.prototype.valueOf = function()
{
return "Instance of Foo";
};
Üçüncü olarak, Foo sınıfının parçası olarak
valueOf()
adında bir sabit özellik tanımlayabilirsiniz. Bu teknik, sabit özellik mirası ile prototip mirasını karma olarak kullandığından diğer tekniklerden farklıdır.
valueOf()
öğesini yeniden tanımlamak isteyen tüm Foo alt sınıflarının
override
anahtar sözcüğünü kullanması gerekir. Aşağıdaki kod, Foo'da sabit özellik olarak tanımlanan
valueOf()
öğesini gösterir:
class Foo
{
function valueOf():String
{
return "Instance of Foo";
}
}
AS3 ad alanı
İki ayrı miras mekanizması, sabit özellik mirası ve prototip mirasının olması, çekirdek sınıfların özellikleri ve yöntemleriyle ilgili ilginç bir uyumluluk zorluğu oluşturur. ActionScript'in esas aldığı ECMAScript dil belirtimiyle uyumluluk için prototip mirasının kullanılması gerekir, başka bir deyişle, çekirdek sınıfın özellikleri ve yöntemleri o sınıfın prototip nesnesinde tanımlanır. Diğer yandan, ActionScript 3.0 ile uyumluluk için sabit özellik mirasının kullanılması gerekir, başka bir deyişle, çekirdek sınıfın özellikleri ve yöntemleri,
const
,
var
ve
function
anahtar sözcükleri kullanılarak sınıf tanımında tanımlanır. Üstelik, prototip sürümleri yerine sabit özelliklerin kullanılması, çalışma zamanı performansında önemli ölçüde artış sağlayabilir.
ActionScript 3.0, çekirdek sınıfları için hem prototip mirasını hem de sabit özellik mirasını kullanarak bu sorunu çözer. Çekirdek sınıfların her biri iki özellik ve yöntem kümesi içerir. Kümelerden biri, ECMAScript belirtimiyle uyumluluk sağlamak için prototip nesnesinde tanımlanırken, diğeri de ActionScript 3.0 ile uyumluluk sağlamak üzere sabit özellikler ve AS3 ad alanıyla tanımlanır.
AS3 ad alanı, iki özellik ve yöntem kümesi arasında seçim yapılmasına yönelik kullanışlı bir mekanizma sağlar. AS3 ad alanını kullanmazsanız, çekirdek sınıfın bir örneği, çekirdek sınıfın prototip nesnesinde tanımlanan özellikleri ve yöntemleri miras alır. Sabit özellikler her zaman prototip özelliklerden daha çok tercih edildiği için, AS3 ad alanını kullanmaya karar verirseniz, çekirdek sınıfın bir örneği AS3 sürümlerini miras alır. Başka bir deyişle, kullanılabilir bir sabit özellik olduğunda, aynı ada sahip olan prototip özelliği yerine her zaman bu sabit özellik kullanılır.
Bir özelliğin veya yöntemin AS3 ad alanı sürümünü AS3 ad alanıyla niteleyerek kullanabilirsiniz. Örneğin, aşağıdaki kod,
Array.pop()
yönteminin AS3 sürümünü kullanır:
var nums:Array = new Array(1, 2, 3);
nums.AS3::pop();
trace(nums); // output: 1,2
Alternatif olarak, bir kod bloğu içindeki tüm tanımlar için AS3 ad alanını açmak üzere
use namespace
direktifini kullanabilirsiniz. Örneğin, aşağıdaki kod,
pop()
ve
push()
yöntemleri için AS3 ad alanını açmak üzere
use namespace
direktifini kullanır:
use namespace AS3;
var nums:Array = new Array(1, 2, 3);
nums.pop();
nums.push(5);
trace(nums) // output: 1,2,5
ActionScript 3.0 ayrıca programınızın tamamına AS3 ad alanı uygulayabilmenizi sağlamak üzere her özellik kümesi için derleyici seçenekleri sağlar.
-as3
derleyici seçeneği, AS3 ad alanını temsil ederken,
-es
derleyici seçeneği de prototip mirası seçeneğini (
es
, ECMAScript'i ifade eder) temsil eder. Programınızın tamamı için AS3 ad alanını açmak üzere,
-as3
derleyici seçeneğini
true
değerine ve
-es
derleyici seçeneğini de
false
değerine ayarlayın. Prototip sürümlerini kullanmak için, derleyici seçeneklerini karşıt değerlere ayarlayın. Flash Builder ve Flash Professional için varsayılan derleyici ayarları şunlardır:
-as3 = true
ve
-es = false
.
Herhangi bir çekirdek sınıfı genişletmeyi ve herhangi bir yöntemi geçersiz kılmayı planlıyorsanız, geçersiz kılınmış bir yöntemi nasıl bildirmeniz gerektiğini AS3 ad alanının nasıl etkileyebildiğini anlamanız gerekir. AS3 ad alanını kullanıyorsanız, çekirdek sınıf yönteminin herhangi bir yöntem geçersiz kılması,
override
niteliğiyle birlikte AS3 ad alanını da kullanmalıdır. AS3 ad alanını kullanmıyor ve bir alt sınıfta çekirdek sınıf yöntemini yeniden tanımlamak istiyorsanız, AS3 ad alanını veya
override
anahtar sözcüğünü kullanmamanız gerekir.
|
|
|