Örnek: GeometricShapes

GeometricShapes örnek uygulaması, ActionScript 3.0 kullanılarak aşağıda örnekleri verilen çok sayıda nesne tabanlı kavram ve özelliklerin nasıl uygulanabildiğini gösterir:

  • Sınıfları tanımlama

  • Sınıfları genişletme

  • Çok biçimlilik ve override anahtar sözcüğü

  • Arabirimleri tanımlama, genişletme ve uygulama

Bu aynı zamanda, sınıf örnekleri oluşturan ve böylece bir arabirimin örneği olarak döndürme değerinin nasıl bildirildiğini ve bu döndürülen nesnenin genel olarak nasıl kullanıldığını gösteren bir "fabrika yöntemini" içerir.

Bu örneğin uygulama dosyalarını edinmek için bkz. www.adobe.com/go/learn_programmingAS3samples_flash_tr . GeometricShapes uygulama dosyalarını Samples/GeometricShapes klasöründe bulabilirsiniz. Uygulama aşağıdaki dosyaları içerir:

File

Açıklama

GeometricShapes.mxml

veya

GeometricShapes.fla

Flash (FLA) veya Flex (MXML) içindeki ana uygulama dosyası.

com/example/programmingas3/geometricshapes/IGeometricShape.as

Tüm GeometricShapes uygulama sınıfları tarafından uygulanacak yöntemleri tanımlayan temel arabirim.

com/example/programmingas3/geometricshapes/IPolygon.as

Birden çok kenarı olan GeometricShapes uygulama sınıfları tarafından uygulanacak yöntemleri tanımlayan bir arabirim.

com/example/programmingas3/geometricshapes/RegularPolygon.as

Şeklin merkezi etrafında simetrik olarak konumlandırılmış eşit uzunlukta kenarlara sahip bir geometrik şekil türü.

com/example/programmingas3/geometricshapes/Circle.as

Bir daireyi tanımlayan geometrik şekil türü.

com/example/programmingas3/geometricshapes/EquilateralTriangle.as

Eşit kenar bir üçgeni tanımlayan bir RegularPolygon alt sınıfı.

com/example/programmingas3/geometricshapes/Square.as

Kareyi tanımlayan bir RegularPolygon alt sınıfı.

com/example/programmingas3/geometricshapes/GeometricShapeFactory.as

Belirli bir tür ve boyutta şekiller oluşturulması için fabrika yöntemini içeren bir sınıf.

GeometricShapes sınıflarını tanımlama

GeometricShapes uygulaması, kullanıcının bir geometrik şekil türünü ve boyutunu belirtmesine olanak sağlar. Bu daha sonra şeklin açıklamasını, alanını ve çevre uzunluğunu içeren bir yanıt verir.

Uygulama kullanıcı arabirimi, şeklin türünün seçilmesi, boyutun ayarlanması ve açıklamanın görüntülenmesine yönelik birkaç denetim içerecek şekilde küçük ve basittir. Bu uygulamanın en ilginç bölümü, yüzeyin altında, sınıf yapısında ve arabirimin kendisinde yer alır.

Bu uygulama geometrik şekillerle ilgilidir ancak bunları grafiksel olarak görüntülemez.

Bu örnekte geometrik şekilleri tanımlayan sınıflar ve arabirimler, aşağıdaki diyagramda Unified Modeling Language (UML) notasyonu kullanılarak gösterilmektedir:

Grafiği tam boyut görüntüle
GeometricShapes Örnek Sınıflar

Arabirimlerle ortak davranışı tanımlama

Bu GeometricShapes uygulaması, üç tür şekli ele alır: daireler, kareler ve eşkenar üçgenler. GeometricShapes sınıf yapısı, üç şekil türü için de ortak olan yöntemleri listeleyen IGeometricShape adındaki çok basit bir arabirimle başlar:

package com.example.programmingas3.geometricshapes 
{ 
    public interface IGeometricShape 
    { 
        function getArea():Number; 
        function describe():String; 
    } 
}

Bu arabirim iki yöntemi tanımlar: şeklin alanını hesaplayıp döndüren getArea() yöntemi ve şeklin özelliklerinin metin açıklamasını bir araya getiren describe() yöntemi.

Ayrıca her şeklin çevre uzunluğunu da bilmek isteyebilirsiniz. Ancak dairenin çevresi benzersiz bir şekilde hesaplanır ve bu nedenle de davranış bir üçgenin veya kareninkinden farklıdır. Yine de üçgenler, kareler ve diğer çokgenler arasında yeterince benzerlik olduğundan, yalnızca bunlara yönelik yeni bir arabirim sınıfının tanımlanması mantıklıdır: IPolygon. Ayrıca burada gösterildiği gibi IPolygon arabirimi daha basittir:

package com.example.programmingas3.geometricshapes 
{ 
    public interface IPolygon extends IGeometricShape 
    { 
        function getPerimeter():Number; 
        function getSumOfAngles():Number; 
    } 
}

Bu arabirim, tüm çokgenler için ortak olan iki yöntemi tanımlar: tüm kenarların birleşik uzunluğunu hesaplayan getPerimeter() yöntemi ve tüm iç açıları toplayan getSumOfAngles() yöntemi.

IPolygon arabirimi, IGeometricShape arabirimini genişletir, başka bir deyişle, IPolygon arabirimini uygulayan tüm sınıfların, IGeometricShape arabiriminden iki tane ve IPolygon arabiriminden iki tane olmak üzere dört yöntemin hepsini bildirmesi gerekir.

Şekil sınıflarını tanımlama

Tüm şekil türleri için ortak olan yöntemler hakkında iyice fikir edindikten sonra, şekil sınıflarını tanımlayabilirsiniz. Uygulamanız gereken yöntem sayısı açısından en basit şekil, burada gösterildiği gibi Circle sınıfıdır:

package com.example.programmingas3.geometricshapes 
{ 
    public class Circle implements IGeometricShape 
    { 
        public var diameter:Number; 
         
        public function Circle(diam:Number = 100):void 
        { 
            this.diameter = diam; 
        } 
         
        public function getArea():Number 
        { 
            // The formula is Pi * radius * radius. 
            var radius:Number = diameter / 2; 
            return Math.PI * radius * radius; 
        } 
         
        public function getCircumference():Number 
        { 
            // The formula is Pi * diameter. 
            return Math.PI * diameter; 
        } 
         
        public function describe():String 
        { 
            var desc:String = "This shape is a Circle.\n"; 
            desc += "Its diameter is " + diameter + " pixels.\n"; 
            desc += "Its area is " + getArea() + ".\n"; 
            desc += "Its circumference is " + getCircumference() + ".\n"; 
            return desc; 
        } 
    } 
}

Circle sınıfı, IGeometricShape arabirimini uygular, bu nedenle hem getArea() yöntemi hem de describe() yöntemi için kod sağlamalıdır. Ayrıca, Circle sınıfı için benzersiz olan getCircumference() yöntemini tanımlar. Circle sınıfı da diğer çokgen sınıflarında bulunmayan bir özellik olarak diameter özelliğini bildirir.

Diğer iki şekil türü olan kareler ve eşkenar üçgenler, ortak başka şeylere sahiptir: bunların her biri eşit uzunlukta kenarlara sahiptir ve her ikisi için de çevre uzunluğunu ve iç açıları toplamını hesaplamakta kullanabileceğiniz ortak formüller vardır. Aslında bu ortak formüller, gelecekte de tanımlayacağınız diğer normal çokgenler için de geçerlidir.

RegularPolygon sınıfı hem Square sınıfı hem de EquilateralTriangle sınıfı için üst sınıftır. Üst sınıf, ortak yöntemleri tek bir yerde tanımlamanıza olanak sağlar, böylece alt sınıfların her birinde bunları ayrı ayrı tanımlamanız gerekmez. RegularPolygon sınıfının kodu şöyledir:

package com.example.programmingas3.geometricshapes 
{ 
    public class RegularPolygon implements IPolygon 
    { 
        public var numSides:int; 
        public var sideLength:Number; 
         
        public function RegularPolygon(len:Number = 100, sides:int = 3):void 
        { 
            this.sideLength = len; 
            this.numSides = sides; 
        } 
         
        public function getArea():Number 
        { 
            // This method should be overridden in subclasses. 
            return 0; 
        } 
         
        public function getPerimeter():Number 
        { 
            return sideLength * numSides; 
        } 
         
        public function getSumOfAngles():Number 
        { 
            if (numSides >= 3) 
            { 
                return ((numSides - 2) * 180); 
            } 
            else 
            { 
                return 0; 
            } 
        } 
         
        public function describe():String 
        { 
            var desc:String = "Each side is " + sideLength + " pixels long.\n"; 
            desc += "Its area is " + getArea() + " pixels square.\n"; 
            desc += "Its perimeter is " + getPerimeter() + " pixels long.\n";  
            desc += "The sum of all interior angles in this shape is " + getSumOfAngles() + " degrees.\n";  
            return desc; 
        } 
    } 
}

İlk olarak, RegularPolygon sınıfı, tüm normal çokgenler için ortak olan iki özelliği bildirir: kenarların her birinin uzunluğu ( sideLength özelliği) ve kenar sayısı ( numSides özelliği).

RegularPolygon sınıfı IPolygon arabirimini uygular ve IPolygon arabirim yöntemleri için dört yöntemi de bildirir. Ortak formülleri kullanarak bunlardan ikisini ( getPerimeter() ve getSumOfAngles() yöntemleri) uygular.

getArea() yönteminin formülü şekilden şekle göre değiştiği için, yöntemin temel sınıf sürümü, alt sınıf yöntemleri tarafından miras alınabilen ortak mantığı içeremez. Bunun yerine, alanın hesaplanmadığını belirtmek için 0 varsayılan değerini döndürür. Her şeklin alanını doğru şekilde hesaplamak için, RegularPolygon sınıfının alt sınıfları, getArea() yöntemini geçersiz kılmalıdır.

Aşağıdaki EquilateralTriangle sınıfının kodu, getArea() yönteminin nasıl geçersiz kılındığını gösterir:

package com.example.programmingas3.geometricshapes  
{ 
    public class EquilateralTriangle extends RegularPolygon 
    { 
        public function EquilateralTriangle(len:Number = 100):void 
        { 
            super(len, 3); 
        } 
         
        public override function getArea():Number 
        { 
        // The formula is ((sideLength squared) * (square root of 3)) / 4. 
        return ( (this.sideLength * this.sideLength) * Math.sqrt(3) ) / 4; 
        } 
         
        public override function describe():String 
        { 
                 /* starts with the name of the shape, then delegates the rest 
                 of the description work to the RegularPolygon superclass */ 
        var desc:String = "This shape is an equilateral Triangle.\n"; 
        desc += super.describe(); 
        return desc; 
        } 
    } 
}

override anahtar sözcüğü, EquilateralTriangle.getArea() yönteminin RegularPolygon üst sınıfından getArea() yöntemini kasıtlı olarak geçersiz kıldığını belirtir. EquilateralTriangle.getArea() yöntemi çağrıldığında, önceki kodda bulunan formülü kullanarak alanı hesaplar ve RegularPolygon.getArea() yöntemindeki kod asla çalıştırılmaz.

Buna karşılık, EquilateralTriangle sınıfı, kendi getPerimeter() yöntemi sürümünü tanımlamaz. EquilateralTriangle.getPerimeter() yöntemi çağrıldığında, çağrı miras zincirinde yukarı gider ve RegularPolygon üst sınıfının getPerimeter() yönteminde kodu çalıştırır.

EquilateralTriangle() yapıcısı, üst sınıfının RegularPolygon() yapıcısını açıkça çağırmak için super() deyimini kullanır. Her iki yapıcı da aynı parametre kümesine sahip olsaydı, EquilateralTriangle() yapıcısı tamamen çıkarılabilir ve bunun yerine RegularPolygon() yapıcısı çalıştırılabilirdi. Ancak, RegularPolygon() yapıcısı numSides adında fazladan bir parametre gerektirir. Bu nedenle EquilateralTriangle() yapıcısı, üçgenin kenarının olduğunu belirtmek için len girdi parametresi ve 3 değeriyle birlikte iletilen super(len, 3) öğesini çağırır.

describe() yöntemi ayrıca super() deyimini farklı bir şekilde kullanır. describe() yönteminin RegularPolygon üst sınıf sürümünü çağırmak için kullanır. EquilateralTriangle.describe() yöntemi ilk olarak desc dize değişkenini şeklin türüyle ilgili bir deyime ayarlar. Daha sonra super.describe() öğesini çağırarak RegularPolygon.describe() yönteminin sonuçlarını alır ve bu sonuçları desc dizesine ekler.

Square sınıfı burada ayrıntılı şekilde ele alınmamıştır ancak bu sınıf, EquilateralTriangle sınıfına çok benzeyip bir yapıcı ve getArea() ve describe() yöntemlerinin kendi uygulamalarını sağlar.

Çok biçimlilik ve fabrika yöntemi

Arabirim ve mirastan yararlanan bir sınıf kümesi birçok ilginç şekilde kullanılabilir. Örneğin, şu ana kadar açıklanan şekil sınıflarının tümü IGeometricShape arabirimini uygular veya bir üst sınıfı genişletir. Bu nedenle de, bir değişkeni IGeometricShape örneği olacak şekilde tanımlarsanız, o değişkene yönelik describe() yöntemini çağırmak için söz konusu değişkenin gerçekte Circle sınıfının mı yoksa Square sınıfının mı bir örneği olduğunu bilmenize gerek yoktur.

Aşağıdaki kod, bunun nasıl olduğunu gösterir:

var myShape:IGeometricShape = new Circle(100); 
trace(myShape.describe());

Değişken IGeometricShape arabiriminin bir örneği olarak tanımlansa da temel alınan sınıf Circle olduğundan, myShape.describe() öğesi çağrıldığında Circle.describe() yöntemini çalıştırır.

Bu örnek, çok biçimlilik ilkesinin uygulanmasını gösterir: tamamen aynı yöntem çağrısı, yöntemi çağrılan nesne sınıfına bağlı olarak, farklı bir kodun çalıştırılmasına neden olur.

GeometricShapes uygulaması, fabrika yöntemi olarak bilinen basitleştirilmiş bir tasarım modeli sürümü kullanarak bu türde bir arabirim tabanlı çok biçimliliği uygular. Fabrika yöntemi terimi, temel alınan veri türü veya içerikleri bağlama göre değişebilen bir nesneyi döndüren işlevi ifade eder.

Burada gösterilen GeometricShapeFactory sınıfı, createShape() adındaki bir fabrika yöntemini tanımlar:

package com.example.programmingas3.geometricshapes  
{ 
    public class GeometricShapeFactory  
    { 
        public static var currentShape:IGeometricShape; 
 
        public static function createShape(shapeName:String,  
                                        len:Number):IGeometricShape 
        { 
            switch (shapeName) 
            { 
                case "Triangle": 
                    return new EquilateralTriangle(len); 
 
                case "Square": 
                    return new Square(len); 
 
                case "Circle": 
                    return new Circle(len); 
            } 
            return null; 
        } 
     
        public static function describeShape(shapeType:String, shapeSize:Number):String 
        { 
            GeometricShapeFactory.currentShape = 
                GeometricShapeFactory.createShape(shapeType, shapeSize); 
            return GeometricShapeFactory.currentShape.describe(); 
        } 
    } 
}

createShape() fabrika yöntemi, yeni nesnelerin uygulama tarafından daha genel şekilde işlenebilmesi için yeni nesneleri IGeometricShape örnekleri olarak döndürürken, şekil alt sınıf yapıcılarının, oluşturdukları örneklerin ayrıntılarını tanımlamasına da olanak sağlar.

Önceki örnekte bulunan describeShape() yöntemi, bir uygulamanın daha belirli bir nesnenin genel başvurusunu almak için nasıl fabrika yöntemini kullanabildiğini gösterir. Uygulama, şu şekilde, yeni oluşturulmuş bir Circle nesnesinin açıklamasını alabilir:

GeometricShapeFactory.describeShape("Circle", 100);

describeShape() yöntemi, aynı parametrelerle createShape() fabrika yöntemini çağırarak yeni Circle nesnesini IGeometricShape nesnesi olarak yazılmış currentShape adındaki bir statik değişkende saklar. Daha sonra, currentShape nesnesinde describe() yöntemi çağrılır ve Circle.describe() yöntemini çalıştırıp dairenin ayrıntılı bir açıklamasını döndürmek için bu çağrı otomatik olarak çözümlenir.

Örnek uygulamayı geliştirme

Arabirimlerin ve mirasın gerçek gücü, uygulamanızı geliştirdiğinizde veya değiştirdiğinizde belirgin olur.

Bu örnek uygulamaya yeni bir şekil olarak beşgen eklemek istediğinizi varsayın. Bu durumda, RegularPolygon sınıfını genişleten ve getArea() ve describe() yöntemlerinin kendi sürümlerini tanımlayan bir Pentagon sınıfı oluşturursunuz. Daha sonra, uygulamanın kullanıcı arabiriminde açılır kutuya yeni bir Pentagon seçeneği eklersiniz. Ve işte hepsi budur. Pentagon sınıfı miras yoluyla RegularPolygon sınıfından getPerimeter() yönteminin ve getSumOfAngles() yönteminin işlevselliğini otomatik olarak alır. Pentagon örneği, IGeometricShape arabirimini uygulayan bir sınıftan miras aldığından, IGeometricShape örneği olarak da değerlendirilebilir. Başka bir deyişle, yeni bir şekil türü eklemek için, GeometricShapeFactory sınıfındaki yöntemlerden herhangi birinin yöntem imzasını değiştirmeniz gerekmez. (Dolayısıyla, GeometricShapeFactory sınıfını kullanan kodlardan herhangi birini de değiştirmeniz gerekmez.)

Arabirimlerin ve mirasın bir uygulamaya yeni özellikler eklemeye yönelik iş yükünü nasıl azalttığını görmek için, uygulama amacıyla Geometric Shapes örneğine bir Pentagon sınıfı eklemek isteyebilirsiniz.