Son zamanlarda TypeScript ile ilgili bir şeyler paylaşmaya çalışıyorum. Yine TypeScript’den bahsediyor olacağım. Bu sefer TypeScript’de OOP’den aşina olduğumuz “Inheritance” kavramını TypeScript’de nasıl oluşturuyoruz bunu anlatmaya çalışacağım. Önceki yazılarda örneklendirdiğim, kod parçalarından devam edeceğim için, önceki yazılara bir göz atmanızı tavsiye ederim. Zaten karmaşık bir dilim var ve bazen çok saçmalıyorum farkındayım.(Buna da bir ara ayrıca değiniyor olacağım). Neyse…Siz yine de mutlaka bir okuyun.

 

Javascript’in genişletilebilir özelliğini, TypeScript’de de, sınıfları “extend“(keyword) ederek kullanabiliyoruz. Ama tabiki bazı şeyleri yapamıyoruz. Bunlardan en önemlisi C#’da ana sınıfta, protected keyword’ü ile koruma altına aldığımız değişkenlerimize türettiğimiz sınıfta ulaşabiliyor olmamız. Ne yazık ki TypeScript’de bu mevcut değil. Şu an ki versiyonunda yok, v1.0’da da olacakmış gibi gözükmüyor. TypeScript’de türettiğimiz sınıfta, ana sınıftaki bir değişkene ulaşmak istiyorsak eğer, ana sınıfta o değişkeni public olarak tanımlamamız gerekmekte. Bunun dışında abstract kavramını da ne yazık ki TypeScript’de kullanamıyoruz.

Önceki yazılarda, Note diye bir sınıf yapmıştım hatırlarsanız. Bu sefer o sınıftan türeyen yeni bir sınıf yaratalım. Bu sınıfta ek olarak, saati gösterebileceğimiz bir ekleme yapalım. Alışveriş listemize bir şey eklediğimiz zaman artık onun saatini de göstermiş olalım bu sayede.


class ExtendedNote extends Note {
    private _date: HTMLElement;

    //Eğer sınıfımızın constructor'ını yazacaksak
    //burada önemli bir nokta var.
    //Basesınıfın da constructor'ını çağırabilmemiz
    //için super() metodunu kullanmamız gerekmekte.
    constructor(text: string) {

        super(text);
        this._date = document.createElement("div");
        this._date.innerText = "Added @ "+ new Date().toTimeString();
        this._date.innerText += this.GetText();
        this._container.appendChild(this._date);

    }

    public ToString(): string
    {
        return this._date.innerText;
    }

    //Note sınıfında olan GetText'i bu şekilde override edebiliriz.
    //Burada dikkat ederseniz super keyword'ü ile Note
    //sınıfındaki GetText metodunu da kullanabiliyoruz.
    public GetText():string
    {
        //super.GetText(),Note sınıfındaki GetText'i çağıracaktır.
        return super.GetText()+' ExtendedNote';
    }

}

Burada “extends” keyword’ü ile ExtendedNote sınıfımız Note sınıfından türemiş oluyor. ExtendedNote sınıfından, Note sınıfında public olarak belirtilmiş tüm değişkenlere ve metodlara ulaşabiliriz.

TypeScript’de base class’da ki bir metodu ezebiliyoruz. Yani türettiğimiz yeni sınıfta, önceki metodun işleyişini değiştirebiliyoruz. Bunun için super keyword’ünü kullanıyoruz. Burada özellikle belirtmek isterim ki super keyword’ü ile base class’daki sadece public fonksiyonlara ulaşabilirsiniz.

Önceki örneklerde yaratmış olduğum CustomHTMLControl’de küçük bir değişiklik ile artık bu ExtendedNote’umuzu kullanabiliriz.

    public onClick(ev: MouseEvent) {
        //Listemizdeki eleman sayısını artırıyoruz.
        //Belki bu sayıyı göstermek isteriz.
        this.noteCount += 1;

        //Array'e ekliyoruz.
        this._notes.push(new ExtendedNote(this.inputField.value));
        this.inputField.value = '';
        this.Render();

    }

Böylece TypeScript’de, OOP’den aşina olduğumuz kavramlar ile çok fazla bir değişiklik yapmadan, sadece yeni bir sınıf yazarak aslında belki de, uygulamamızı genişletebiliyoruz.

TypeScript

Yazının devamında komple güncellenmiş örneğin kodlarına ulaşabilirsiniz. Umarım yavaş yavaş bazı şeyler daha da anlaşılıyor oluyordur.


//Alışveriş listemizdeki elemanları temsil edecek
//Note diye bir sınıfımız olsun.
class Note {

    //DOM'daki HTMLElement tipinde karşılığı
    public _container: HTMLElement;
    //Listedeki elemanımız içeriği
    private _text: string;

    constructor(t: string) {
        //Constructor'da text'imizi set ediyoruz.
        this._text = t;

        //DOM'da ki elemanı bir DIV olarak tanımlayıp
        //text'i bu div'in innertext değişkenine atıyoruz.
        this._container = document.createElement("div");
        this._container.innerText = this._text;

        //DIV'imize tıklandığı zaman listemizdeki elemanın
        //üstünü çizip,italik yapıyoruz
        this._container.onclick = () =>
        {
            this._container.style.textDecoration = 'line-through';
            this._container.style.fontStyle = 'italic';
        }
    }

    public GetText(): string {
        return this._text;
    }

    //Listemizdeki item'ı verilen HTML parent elemanına
    //ekleyip, render yapıyoruz diyebiliriz.
    public Render(parent:HTMLElement) {
        parent.appendChild(this._container);
    }

}

class ExtendedNote extends Note {
    private _date: HTMLElement;

    //Eğer sınıfımızın constructor'ını yazacaksak
    //burada önemli bir nokta var.
    //Basesınıfın da constructor'ını çağırabilmemiz
    //için super() metodunu kullanmamız gerekmekte.
    constructor(text: string) {

        super(text);
        this._date = document.createElement("div");
        this._date.innerText = "Added @ "+ new Date().toTimeString();
        this._date.innerText += this.GetText();
        this._container.appendChild(this._date);

    }

    public ToString(): string
    {
        return this._date.innerText;
    }

    //Note sınıfında olan GetText'i bu şekilde override edebiliriz.
    //Burada dikkat ederseniz super keyword'ü ile Note
    //sınıfındaki GetText metodunu da kullanabiliyoruz.
    public GetText():string
    {
        //super.GetText(),Note sınıfındaki GetText'i çağıracaktır.
        return super.GetText()+' ExtendedNote';
    }

}

class CustomHTMLControl {

    container: HTMLElement;
    header: HTMLElement;
    content: HTMLElement;
    footer: HTMLElement;
    inputField: HTMLInputElement;
    private button: HTMLInputElement;

    //Listemizde ki elemanları Note tipinde bir array'de tutuyoruz.
    private _notes: Note[] = [];
    private noteCount: number = 0;

    constructor(element: HTMLElement) {

        //DOM içerisindeki gerekli elemanları yaratıyoruz
        //Burada içeriği almak için bir tane input alanımız
        //bir tane button yeterli olacaktır.
        //Button'a tıkladığımızda, Note tipinde bir elemanı
        //listemize ekliyoruz.
        this.container = element;
        this.header = document.createElement('div');
        this.header.innerText = 'This is a Shopping List';
        this.container.appendChild(this.header);

        this.inputField = document.createElement("input");
        this.inputField.type = "text";

        this.container.appendChild(this.inputField);

        this.content = document.createElement("div");
        this.button = document.createElement("input");
        this.button.type = "button";
        this.button.value = "Add";

        //Burada bind(this) ifadesini kullanmazsak
        //onClick metodunda bu sınıf içerisinde ki local
        //değişkenlere ulaşamıyor oluruz. Bunun yerine
        //Fat Arrow fonksiyon deklarasyonunu da yapabiliriz.
        //TypeScript Fat Arrow deklarasyonunu da destekliyor.
        this.button.onclick = this.onClick.bind(this);

        this.content.appendChild(this.button);
        this.container.appendChild(this.content);

        this.footer = document.createElement("div");

        this.container.appendChild(this.footer);
    }

    public onClick(ev: MouseEvent) {
        //Listemizdeki eleman sayısını artırıyoruz.
        //Belki bu sayıyı göstermek isteriz.
        this.noteCount += 1;

        //Array'e ekliyoruz.
        this._notes.push(new ExtendedNote(this.inputField.value));
        this.inputField.value = '';
        this.Render();

    }

    public Render(): void {
        //Array'mizden alıp; -ki burada aldığımız eleman Note tipinde olacaktır.
        var note = this._notes.pop();
        note.Render(this.content);
    }

}

window.onload = () => {
    //HTML sayfamızdaki herhangi bir div içeriğine ekliyoruz
    //oluşturduğumuz kontrolü
    var parent = document.getElementById('content');
    var customControl = new CustomHTMLControl(parent);

};

TypeScript kodumuzun derlenmiş ve oluşan Javascript’i de aşağıdaki gibi olacaktır. Karşılaştırıp bazı şeylerin nasıl olduğunu anlamak adına belki daha doğru olacaktır.

var __extends = this.__extends || function (d, b) {
    for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];
    function __() { this.constructor = d; }
    __.prototype = b.prototype;
    d.prototype = new __();
};
//Alışveriş listemizdeki elemanları temsil edecek
//Note diye bir sınıfımız olsun.
var Note = (function () {
    function Note(t) {
        var _this = this;
        //Constructor'da text'imizi set ediyoruz.
        this._text = t;

        //DOM'da ki elemanı bir DIV olarak tanımlayıp
        //text'i bu div'in innertext değişkenine atıyoruz.
        this._container = document.createElement("div");
        this._container.innerText = this._text;

        //DIV'imize tıklandığı zaman listemizdeki elemanın
        //üstünü çizip,italik yapıyoruz
        this._container.onclick = function () {
            _this._container.style.textDecoration = 'line-through';
            _this._container.style.fontStyle = 'italic';
        };
    }
    Note.prototype.GetText = function () {
        return this._text;
    };

    //Listemizdeki item'ı verilen HTML parent elemanına
    //ekleyip, render yapıyoruz diyebiliriz.
    Note.prototype.Render = function (parent) {
        parent.appendChild(this._container);
    };
    return Note;
})();

var ExtendedNote = (function (_super) {
    __extends(ExtendedNote, _super);
    function ExtendedNote(text) {
        _super.call(this, text);
        this._date = document.createElement("div");
        this._date.innerText = "Added @ " + new Date().toTimeString();
        this._date.innerText += this.GetText();
        this._container.appendChild(this._date);
    }
    ExtendedNote.prototype.ToString = function () {
        return this._date.innerText;
    };

    //Note sınıfında olan GetText'i bu şekilde override edebiliriz.
    ExtendedNote.prototype.GetText = function () {
        return _super.prototype.GetText.call(this) + ' ExtendedNote';
    };
    return ExtendedNote;
})(Note);

var CustomHTMLControl = (function () {
    function CustomHTMLControl(element) {
        //Listemizde ki elemanları Note tipinde bir array'de tutuyoruz.
        this._notes = [];
        this.noteCount = 0;
        //DOM içerisindeki gerekli elemanları yaratıyoruz
        //Burada içeriği almak için bir tane input alanımız
        //bir tane button yeterli olacaktır.
        //Button'a tıkladığımızda, Note tipinde bir elemanı
        //listemize ekliyoruz.
        this.container = element;
        this.header = document.createElement('div');
        this.header.innerText = 'This is a Shopping List';
        this.container.appendChild(this.header);

        this.inputField = document.createElement("input");
        this.inputField.type = "text";

        this.container.appendChild(this.inputField);

        this.content = document.createElement("div");
        this.button = document.createElement("input");
        this.button.type = "button";
        this.button.value = "Add";

        //Burada bind(this) ifadesini kullanmazsak
        //onClick metodunda bu sınıf içerisinde ki local
        //değişkenlere ulaşamıyor oluruz. Bunun yerine
        //Fat Arrow fonksiyon deklarasyonunu da yapabiliriz.
        //TypeScript Fat Arrow deklarasyonunu da destekliyor.
        this.button.onclick = this.onClick.bind(this);

        this.content.appendChild(this.button);
        this.container.appendChild(this.content);

        this.footer = document.createElement("div");

        this.container.appendChild(this.footer);
    }
    CustomHTMLControl.prototype.onClick = function (ev) {
        //Listemizdeki eleman sayısını artırıyoruz.
        //Belki bu sayıyı göstermek isteriz.
        this.noteCount += 1;

        //Array'e ekliyoruz.
        this._notes.push(new ExtendedNote(this.inputField.value));
        this.inputField.value = '';
        this.Render();
    };

    CustomHTMLControl.prototype.Render = function () {
        //Array'mizden alıp; -ki burada aldığımız eleman Note tipinde olacaktır.
        var note = this._notes.pop();
        note.Render(this.content);
    };
    return CustomHTMLControl;
})();

window.onload = function () {
    //HTML sayfamızdaki herhangi bir div içeriğine ekliyoruz
    //oluşturduğumuz kontrolü
    var parent = document.getElementById('content');
    var customControl = new CustomHTMLControl(parent);
};
//# sourceMappingURL=app.js.map