Miras

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