Miras, programcıların varolan sınıfları esas alarak yeni sınıflar geliştirmesine olanak sağlayan bir kod yeniden kullanım şeklidir. Varolan sınıflar genellikle
temel sınıflar
veya
üst sınıflar
olarak adlandırılırken, yeni sınıflar genellikle
alt sınıflar
olarak adlandırılır. Mirasın en büyük avantajı, siz bir temel sınıftaki kodu yeniden kullanırken varolan kodu değiştirmeden bırakmanıza olanak sağlamasıdır. Üstelik miras, diğer sınıfların temel sınıfla etkileşim kurma şekli üzerinde herhangi bir değişiklik gerektirmez. Tamamen test edilmiş veya hala kullanımda olabilecek varolan bir sınıfı değiştirmek yerine, mirası kullanarak sınıfı, ek özellik ve yöntemlerle genişletebileceğiniz tümleşik bir modül olarak değerlendirebilirsiniz. Aynı şekilde, bir sınıfın başka bir sınıftan miras aldığını belirtmek için
extends
anahtar sözcüğünü kullanırsınız.
Miras aynı zamanda kodunuzda
çok biçimlilikten
yararlanmanıza olanak sağlar. Çok biçimlilik, farklı veri türlerine uygulandığında farklı şekilde davranan bir yöntem için tek bir yöntem adı kullanma yeteneğidir. Bunun basit bir örneği, Circle ve Square adında iki alt sınıf içeren Shape adındaki bir temel sınıftır. Shape sınıfı, şeklin alanını döndüren,
area()
adında bir yöntemi tanımlar. Çok biçimlilik uygulanıyorsa, Circle ve Square türündeki nesnelerde
area()
yöntemini çağırıp sizin için doğru hesaplamaların yapılmasını sağlayabilirsiniz. Miras, alt sınıfların temel sınıflardaki yöntemleri miras almasına, yeniden tanımlamasına veya
geçersiz kılmasına
olanak sağlayarak çok biçimliliği etkinleştirir. Aşağıdaki örnekte,
area()
yöntemi Circle ve Square sınıfları tarafından yeniden tanımlanır:
class Shape
{
public function area():Number
{
return NaN;
}
}
class Circle extends Shape
{
private var radius:Number = 1;
override public function area():Number
{
return (Math.PI * (radius * radius));
}
}
class Square extends Shape
{
private var side:Number = 1;
override public function area():Number
{
return (side * side);
}
}
var cir:Circle = new Circle();
trace(cir.area()); // output: 3.141592653589793
var sq:Square = new Square();
trace(sq.area()); // output: 1
Her sınıf bir veri türünü tanımladığından, miras kullanılması, temel sınıf ile temel sınıfı genişleten sınıf arasında özel bir ilişki oluşturur. Bir alt sınıfın, temel sınıfın tüm özelliklerine sahip olması garantilenir, başka bir deyişle, alt sınıfın bir örneği her zaman temel sınıfın bir örneği yerine geçebilir. Örneğin, bir yöntem Shape türünde bir parametreyi tanımlarsa, aşağıdaki gibi, Circle öğesi Shape öğesini genişlettiğinden Circle türünde bir argüman iletilmesi geçerli bir durumdur:
function draw(shapeToDraw:Shape) {}
var myCircle:Circle = new Circle();
draw(myCircle);
Örnek özellikleri ve miras
function
,
var
veya
const
anahtar sözcükleriyle tanımlanmış bir örnek özelliği, özellik temel sınıfta
private
niteliğiyle bildirilmediği sürece, tüm alt sınıflar tarafından miras alınır. Örneğin, ActionScript 3.0'daki Event sınıfı, tüm olay nesneleri için ortak olan özellikleri miras alan çok sayıda alt sınıfa sahiptir.
Bazı olay türleri için, Event sınıfı, olayın tanımlanması için gerekli olan tüm özellikleri içerir. Bu olay türleri, Event sınıfında tanımlı olanlar dışında bir örnek özelliği gerektirmez. Bu olaylara örnek olarak, veri başarıyla yüklendiğinde gerçekleşen
complete
olayı ve bir ağ bağlantısı kurulduğunda gerçekleşen
connect
olayı verilebilir.
Aşağıdaki örnek, alt sınıflar tarafından miras alınan özellik ve yöntemlerden bazılarını gösteren bir Event sınıfı alıntısıdır. Özellikler miras alındığından, tüm alt sınıflar bu özelliklere erişebilir.
public class Event
{
public function get type():String;
public function get bubbles():Boolean;
...
public function stopPropagation():void {}
public function stopImmediatePropagation():void {}
public function preventDefault():void {}
public function isDefaultPrevented():Boolean {}
...
}
Diğer olay türleri, Event sınıfında kullanılamayan benzersiz özellikleri gerektirir. Bu olaylar, Event sınıfının alt sınıfları kullanılarak tanımlanır, böylece Event sınıfında tanımlanan özelliklere yeni özellikler eklenebilir. Böyle bir alt sınıfa örnek olarak,
mouseMove
ve
click
olayları gibi fare hareketiyle veya fare tıklatmalarıyla ilişkilendirilmiş olaylara özgü özellikler ekleyen MouseEvent sınıfı verilebilir. Aşağıdaki örnek, alt sınıfta bulunan ancak temel sınıfta bulunmayan özelliklerin tanımını gösteren bir MouseEvent alıntısıdır:
public class MouseEvent extends Event
{
public static const CLICK:String= "click";
public static const MOUSE_MOVE:String = "mouseMove";
...
public function get stageX():Number {}
public function get stageY():Number {}
...
}
Erişim denetimi belirticileri ve miras
Bir özellik
public
anahtar sözcüğüyle bildirilirse, özellik her yerdeki kodlar tarafından görülebilir. Başka bir deyişle,
private
,
protected
ve
internal
anahtar sözcüklerinin aksine,
public
anahtar sözcüğü özellik mirasına herhangi bir kısıtlama koymaz.
Bir özellik
private
anahtar sözcüğüyle bildirilirse, yalnızca kendisini tanımlayan sınıfta görülebilir, başka bir deyişle, alt sınıflar tarafından miras alınmaz. Bu davranış,
private
anahtar sözcüğünün daha çok ActionScript 3.0
protected
anahtar sözcüğü gibi davrandığı önceki ActionScript sürümlerinden farklıdır.
protected
anahtar sözcüğü, bir özelliğin yalnızca kendisini tanımlayan sınıfta değil, tüm alt sınıflar için de görülebilir olduğunu belirtir. Java programlama dilindeki
protected
anahtar sözcüğünün aksine, ActionScript 3.0'daki
protected
anahtar sözcüğü, bir özelliği aynı paketteki diğer tüm sınıflar tarafından görülebilir duruma getirmez. ActionScript 3.0'da, yalnızca alt sınıflar
protected
anahtar sözcüğüyle bildirilen bir özelliğe erişebilir. Üstelik, alt sınıf temel sınıfla aynı pakette de olsa farklı pakette de olsa, korumalı özelliği o alt sınıf tarafından görülebilir.
Bir özelliğin görünebilirliğini tanımlandığı paketle sınırlandırmak için,
internal
anahtar sözcüğünü kullanın veya herhangi bir erişim denetimi belirticisi kullanmayın.
internal
erişim denetimi belirticisi, herhangi bir erişim denetimi belirticisi belirtilmediğinde geçerli olan varsayılandır.
internal
olarak işaretlenmiş bir özellik yalnızca aynı pakette bulunan bir alt sınıf tarafından miras alınır.
Erişim denetimi belirticilerinin her birinin, paket sınırları boyunca mirası nasıl etkilediğini görmek için aşağıdaki örneği kullanabilirsiniz. Aşağıdaki örnek, AccessControl adında bir ana uygulama sınıfını ve Base ve Extender adında başka iki sınıfı tanımlar. Base sınıfı, foo adındaki bir pakette ve Base sınıfının alt sınıfı olan Extender sınıfı da bar adındaki bir pakettedir. AccessControl sınıfı yalnızca Extender sınıfını içe aktarır ve Base sınıfında tanımlanmış
str
adındaki bir değişkene erişmeye çalışan Extender örneğini oluşturur.
str
değişkeni,
public
olarak bildirilir, böylece aşağıdaki alıntıda gösterildiği gibi kod derleme yapar ve çalıştırılır:
// Base.as in a folder named foo
package foo
{
public class Base
{
public var str:String = "hello"; // change public on this line
}
}
// Extender.as in a folder named bar
package bar
{
import foo.Base;
public class Extender extends Base
{
public function getString():String {
return str;
}
}
}
// main application class in file named AccessControl.as
package
{
import flash.display.MovieClip;
import bar.Extender;
public class AccessControl extends MovieClip
{
public function AccessControl()
{
var myExt:Extender = new Extender();
trace(myExt.str);// error if str is not public
trace(myExt.getString()); // error if str is private or internal
}
}
}
Diğer erişim denetimi belirticilerinin, önceki örnekte derlemeyi ve çalıştırmayı nasıl etkilediğini görmek için,
AccessControl
sınıfından aşağıdaki satırı sildikten veya aşağıdaki satırın yorumunu kaldırdıktan sonra,
str
değişkeninin erişim denetimi belirticisini
private
,
protected
ya da
internal
olarak değiştirin:
trace(myExt.str);// error if str is not public
Değişkenleri geçersiz kılmaya izin verilmez
var
veya
const
anahtar sözcükleriyle bildirilen özellikler miras alınır ancak geçersiz kılınamaz. Bir özelliğin geçersiz kılınması, bir alt sınıfta özelliğin yeniden tanımlanması anlamına gelir. Geçersiz kılınabilen tek özellik türü al ve ayarla erişimcileridir (
function
anahtar sözcüğüyle bildirilmiş özellikler). Bir örnek değişkenini geçersiz kılamasanız da, örnek değişkeni için alıcı ve ayarlayıcı yöntemleri oluşturup yöntemleri geçersiz kılarak benzer bir işlevi elde edebilirsiniz.
Yöntemleri geçersiz kılma
Bir yöntemin geçersiz kılınması, miras alınan bir yöntemin davranışının yeniden tanımlanması anlamına gelir. Statik yöntemler miras alınmaz ve geçersiz kılınamaz. Ancak, örnek yöntemleri, alt sınıflar tarafından miras alınır ve şu iki kriter karşılandığı sürece geçersiz kılınabilir:
-
Örnek yöntemi temel sınıfta
final
anahtar sözcüğüyle bildirilmez.
final
anahtar sözcüğü bir örnek yöntemiyle kullanıldığında, programcının, alt sınıfların yöntemi geçersiz kılmasını önleme amacında olduğunu belirtir.
-
Örnek yöntemi temel sınıfta
private
erişim denetimi belirticisiyle bildirilmez. Bir yöntem temel sınıfta
private
olarak işaretlenmişse, temel sınıf yöntemi alt sınıf tarafından görülemeyeceğinden, alt sınıfta aynı şekilde adlandırılmış yöntemi tanımlarken
override
anahtar sözcüğünün kullanılması gerekmez.
Bu kriterleri karşılayan bir örnek yöntemini geçersiz kılmak için, aşağıdaki şekilde alt sınıftaki yöntem tanımının
override
anahtar sözcüğünü kullanması ve yöntemin üst sınıf sürümüyle eşleşmesi gerekir:
-
Geçersiz kılma yönteminin, temel sınıf yöntemiyle aynı erişim denetimi düzeyine sahip olması gerekir. Dahili olarak işaretlenmiş yöntemler, herhangi bir erişim denetimi belirticisi içermeyen yöntemlerle aynı erişim denetimi düzeyine sahiptir.
-
Geçersiz kılma yönteminin, temel sınıf yöntemiyle aynı sayıda parametreye sahip olması gerekir.
-
Geçersiz kılma yöntemi parametrelerinin, temel sınıf yöntemindeki parametrelerle aynı veri türü ek açıklamalarına sahip olması gerekir.
-
Geçersiz kılma yönteminin, temel sınıf yöntemiyle aynı döndürme türüne sahip olması gerekir.
Her ikisinin de parametre sayısı ve parametrelerinin veri türü eşleştiği sürece, geçersiz kılma yöntemindeki parametrelerin adları ile temel sınıftaki parametrelerin adlarının eşleşmesi gerekmez.
super deyimi
Programcılar bir yöntemi geçersiz kılarken genellikle davranışı tamamen değiştirmek yerine geçersiz kıldıkları üst sınıf yönteminin davranışına ekleme yapmak ister. Bunun için de, bir alt sınıftaki yöntemin kendi üst sınıf sürümünü çağırmasına olanak sağlayan bir mekanizma gerekir.
super
deyimi, anında üst sınıfa başvuru içererek bu mekanizmayı sağlar. Aşağıdaki örnek,
thanks()
adındaki bir yöntemi içeren Base adında bir sınıfı ve
thanks()
yöntemini geçersiz kılan Extender adındaki bir Base sınıfının alt sınıfını tanımlar.
Extender.thanks()
yöntemi,
Base.thanks()
öğesini çağırmak için
super
deyimini kullanır.
package {
import flash.display.MovieClip;
public class SuperExample extends MovieClip
{
public function SuperExample()
{
var myExt:Extender = new Extender()
trace(myExt.thanks()); // output: Mahalo nui loa
}
}
}
class Base {
public function thanks():String
{
return "Mahalo";
}
}
class Extender extends Base
{
override public function thanks():String
{
return super.thanks() + " nui loa";
}
}
Alıcıları ve ayarlayıcıları geçersiz kılma
Bir üst sınıfta tanımlanmış değişkenleri geçersiz kılamasanız da, alıcıları ve ayarlayıcıları geçersiz kılabilirsiniz. Örneğin, aşağıdaki kod, ActionScript 3.0'daki MovieClip sınıfında tanımlanmış
currentLabel
adındaki bir alıcıyı geçersiz kılar:
package
{
import flash.display.MovieClip;
public class OverrideExample extends MovieClip
{
public function OverrideExample()
{
trace(currentLabel)
}
override public function get currentLabel():String
{
var str:String = "Override: ";
str += super.currentLabel;
return str;
}
}
}
OverrideExample sınıf yapıcısında
trace()
çıktısı
Override: null
olup bu, örneğin miras alınan
currentLabel
özelliğini geçersiz kılabildiğini gösterir.
Statik özellikler miras alınmaz
Statik özellikler, alt sınıflar tarafından miras alınmaz. Başka bir deyişle, statik özelliklere bir alt sınıfın örneği üzerinden erişilemez. Statik özelliğe yalnızca tanımlanmış olduğu sınıf nesnesi üzerinden erişilebilir. Örneğin, aşağıdaki kod, Base adında bir temel sınıfı ve Base sınıfını genişleten Extender adında bir alt sınıfı tanımlar.
test
adındaki bir statik değişken Base sınıfında tanımlanır. Aşağıdaki alıntıda yazılı kod katı modda derleme yapmaz ve standart modda bir çalışma zamanı hatası oluşturur.
package {
import flash.display.MovieClip;
public class StaticExample extends MovieClip
{
public function StaticExample()
{
var myExt:Extender = new Extender();
trace(myExt.test);// error
}
}
}
class Base {
public static var test:String = "static";
}
class Extender extends Base { }
Aşağıdaki kodda gösterildiği gibi,
test
statik değişkenine yalnızca sınıf nesnesi üzerinden erişilebilir:
Base.test;
Ancak aynı adı statik özellik olarak kullanıp bir örnek özelliğinin tanımlanmasına izin verilir. Böyle bir örnek özelliği, statik özellikle aynı sınıfta veya bir alt sınıfta tanımlanabilir. Örneğin, önceki örnekte yer alan Base sınıfı,
test
adında bir örnek özelliğine sahip olabilirdi. Örnek özelliği Extender sınıfı tarafından miras alındığından, aşağıdaki kod derleme yapar ve çalıştırılır. Test örneği değişkeninin tanımı Extender sınıfına kopyalanmayıp taşınırsa da kod derleme yapar ve çalıştırılır.
package
{
import flash.display.MovieClip;
public class StaticExample extends MovieClip
{
public function StaticExample()
{
var myExt:Extender = new Extender();
trace(myExt.test);// output: instance
}
}
}
class Base
{
public static var test:String = "static";
public var test:String = "instance";
}
class Extender extends Base {}
Statik özellikler ve kapsam zinciri
Statik özellikler miras alınmasa da, bunlar kendilerini tanımlayan sınıfın ve o sınıfın alt sınıflarının kapsam zincirinde bulunur. Bu nedenle de, statik özelliklerin hem tanımlandıkları sınıfın hem de alt sınıfların
kapsamında
olduğu söylenebilir. Başka bir deyişle, bir statik özellik yalnızca statik özelliği tanımlayan sınıfın ve o sınıfın alt sınıflarının gövdesinde doğrudan erişilebilir durumdadır.
Aşağıdaki örnek, Base sınıfında tanımlanmış statik
test
değişkeninin, Extender sınıfının kapsamında olduğunu göstermek için, önceki örnekte tanımlanan sınıfları değiştirir. Başka bir deyişle, Extender sınıfı,
test
öğesini tanımlayan sınıfın adını değişkene önek olarak eklemeden statik
test
değişkenine erişebilir.
package
{
import flash.display.MovieClip;
public class StaticExample extends MovieClip
{
public function StaticExample()
{
var myExt:Extender = new Extender();
}
}
}
class Base {
public static var test:String = "static";
}
class Extender extends Base
{
public function Extender()
{
trace(test); // output: static
}
}
Bir örnek özelliği, aynı sınıfta veya bir üst sınıfta statik özellik olarak aynı adı kullanacak şekilde tanımlanırsa, örnek özelliği kapsam zincirinde daha yüksek bir öncelik elde eder. Örnek özelliğinin statik özelliği
gölgelediği
, başka bir deyişle, statik özelliğin değeri yerine örnek özelliğinin değerinin kullanıldığı söylenebilir. Örneğin, aşağıdaki kod, Extender sınıfı
test
adında bir örnek değişkeni tanımlarsa,
trace()
deyiminin, statik değişkenin değerini değil, örnek değişkeninin değerini kullandığını gösterir:
package
{
import flash.display.MovieClip;
public class StaticExample extends MovieClip
{
public function StaticExample()
{
var myExt:Extender = new Extender();
}
}
}
class Base
{
public static var test:String = "static";
}
class Extender extends Base
{
public var test:String = "instance";
public function Extender()
{
trace(test); // output: instance
}
}
|
|
|