Nesne Yönelimli Programlama Nedir?

Nesne Yönelimli Programlama (ing: Object-oriented Programming), yazılımdaki her işlevin nesne olarak tasarlandığı programlama biçimidir. Nesne yönelimli programlama yaklaşımında, veriler ve ilişkili kodları içeren nesneler kullanılır. Nesneler sınıf (ing.: class) adlı şablonlar kullanılarak oluşturulur. Nesne içerisinde veriler özellik veya nitelik (ing.: property, attribute, field) denilen değişkenlerde, kodlar ise fonksiyon veya metot (ing.: function, method) adlı yapılar şeklinde tutulur. Bir programlama dilinin nesne yönelimli olarak sınıflandırılması için dört esası desteklemesi gerekmektedir;

  • Sarma veya Kapsülleme (ing.: Encapsulation),
  • Kalıtım (ing.: Inheritance)
  • Soyutlama (ing.: Abstraction),
  • Çok Biçimlilik (ing.: Polymorphism)

Kapsülleme

Kapsülleme, nesnenin değişkenlerini ve metotlarını diğer nesnelerden saklayarak erişimi sınırlandırır ve sadece istenilen metot ve değişkenlere erişmeyi sağlayarak yanlış kullanımdan koruyan ilkedir. Amaç verilerin güvenliğini sağlamaktır. Public, Private ve Protected gibi erişim belirliyecileri ile nesne içeriğine erişim belirlenir. Açık (ing.: Public) erişim belirleyicisi ile nesne içeriğine dışarıdan erişilebilir, Gizli (ing.: Private) nesne içeriğine erişilemez. Korumalı (ing.: Protected) tanımlanmış nesne öğeleri sadece ilgili sınıfdan örneklendirilmiş nesnelerin içinden ve bu sınıfdan türetilmiş olan alt nesnelerden erişilebilir.

Kalıtım

Kalıtım, bir sınıfın başka sınıftan özelliklerini ve metotlarını miras almasına denir. Bir sınıfın belirli özellik ve tutumlarını bir üst sınıftan alarak, kendisi için farklı olan özellikleri ayrıca uygulayabilir olmasını sağlar. Miras alınan sınıf ana (ing.: parent) sınıf, miras alan sınıf alt (ing.: sub) sınıf olarak adlandırılır. Kalıtım özelliği sayesinde birden fazla sınıfta kullanılan aynı kodların tekrar tekrar yazılması engellenir.

Soyutlama

Soyutlama, bir nesnenin sadece başka nesneler tarafından kullanılan kısımlarının gösterilmesidir. Soyutlamanın amacı gereksiz detayların gizlenmesi ve kod karmaşıklığının azaltılmasıdır. Böylece nesnenin ana işlev ve özelliklerinin basit ve anlaşılır olmasını sağlar. Soyutlama sayesinde gizlenip soyutlanan detaylarda yazılımın geri kalanı etkilenmeden değişiklikler kolaylıkla yapılabilir.

Çok Biçimlilik

Çok Biçimlilik, aynı sınıftan türeyen sınıflara farklı davranışlar kazandırmayı sağlar. Aynı sınıftan türeyen nesnelere aynı arayüz üzerinden erişilir olmasını sağlar ve kod tekrarını azaltır.

JavaScript ve Nesne Yönelimi

Nesne yönelimli programlama yaklaşımı, nesne tabanlı ve sınıf tabanlı olarak ikiye ayrılır. Sınıf tabanlı yaklaşımda; Kapsülleme, Kalıtım, Soyutlama, Çok Biçimlilik ilkelerini uygulayan diller esas alınır. Sınıf tabanlı dillerden bazılarına örnek olarak; Java, Python ve C# sayılabilir. JavaScript ise yapı olarak sınıf tabanlı değil prototip tabanlı bir dildir ve class bulunmaz prototype kullanılır. Prototype JavaScript dilinde en üst temel sınıftır. Tam olarak sınıf yapısı bulunmasa da JavaScript nesne oluşturup uygulamalarda kullanılmasını destekler. 2015 yılında JavaScript diline class anahtar kelimesi eklendi ve sınıf tanımlamak daha da kolaylaştı. Yeni eklenen özelliklerle JavaScript daha çok nesne tabanlı dillere benzese de arka tarafta hâlâ prototip tabanlı yapıyı kullanmaktadır. Özetle JavaScript, nesne yönelimli programlamayı destekleyen prototip tabanlı programlama dilidir denilebilir.

ES6 Sınıf Tanımlamak

JavaScript diline EcmaScript 6 spesifikasyonuyla 2015 yılında eklenen class anahtar kelimesi ile sınıf tanımlamak oldukça kolaylaştırmıştır;

Kod

class Person {
    constructor(firstName, lastName, age) {
        this.firstName = firstName;
        this.lastName = lastName;
        this.age = age;
    }
    
    greet() {
        return `Merhaba! Benim adım; ${this.firstName}!`;
    }
    
}


let person = new Person("Altan", "Tekisim", 43);

console.log(person);            // Person {firstName: 'Altan', lastName: 'Tekisim', age: 43}

console.log(person.greet())     // Merhaba! Benim adım; Altan!

Kapsülleme

Class içindeki bir değişken ya da fonksiyonu nesne dışından erişimini kısıtlamak için private olarak tanımlamak gerekir. Bunun için ilgili alanın başına # karakteri yazılır;

Kod

class Person {
    
    // Private fields
    #firstName;
    #lastName;
    #age;
    
    constructor(firstName, lastName, age) {
        this.#firstName = firstName;
        this.#lastName = lastName;
        this.#age = age;
    }
    
    // Public function
    getFirstName() {
        return this.#firstName;
    }
    
    // Public function
    setFirstName(firstName) {
        if(firstName) {
            this.#firstName = firstName;
        }
    }
    
    // Private function
    #getFullName() {
        return `${this.#firstName} ${this.#lastName}`;
    }
    
    // Public function
    greet() {
        return `Merhaba! Benim adım; ${this.#getFullName()}!`;
    }
    
}


let person = new Person("Altan", "Tekisim", 43);


console.log(person);                    // Person {#getFullName: ƒ, #firstName: 'Altan', #lastName: 'Tekisim', #age: 43}
console.log(person.getFirstName());        // Altan

person.setFirstName("Tayfun")    

console.log(person.greet());             // Merhaba! Benim adım; Tayfun Tekisim!


console.log(person.getFullName());        // Uncaught TypeError: person.getFullName is not a function

Kalıtım

Kalıtım uygulamak için extends anahtar kelimesi kullanılır;

Kod

class Person {
    
    // Private fields
    #firstName;
    #lastName;
    #age;
    
    constructor(firstName, lastName, age) {
        this.#firstName = firstName;
        this.#lastName = lastName;
        this.#age = age;
    }
    
    // Public function
    getFirstName() {
        return this.#firstName;
    }
    
    // Public function
    setFirstName(firstName) {
        if(firstName) {
            this.#firstName = firstName;
        }
    }
    
    // Private function
    #getFullName() {
        return `${this.#firstName} ${this.#lastName}`;
    }
    
    // Public function
    greet() {
        return `Merhaba! Benim adım; ${this.#getFullName()}!`;
    }
    
}


class Student extends Person{
    
    // Private fields
    #courses;
    
    constructor(firstName, lastName, age, courses) {
        super(firstName, lastName, age)
        
        this.#courses = courses;
    }
    
    // Public function
    getCourses() {
        return this.#courses;
    }
    
    // Public function
    learn() {
        return `Merhaba! Benim adım; ${super.getFirstName()}! ${this.#courses} derslerini öğreniyorum.`;
    }
    
}

let student = new Student("Altan", "Tekisim", 43, ["Matematik", "Geometri", "Etimoloji"]);


console.log(student);                // Student {#getFullName: ƒ, #firstName: 'Altan', #lastName: 'Tekisim', #age: 43, #courses: Array(3)}
console.log(student.getFirstName());    // Altan

student.setFirstName("Tayfun");        

console.log(student.greet());            // Merhaba! Benim adım; Tayfun Tekisim!
console.log(student.learn());             // Merhaba! Benim adım; Tayfun! Matematik,Geometri,Etimoloji derslerini öğreniyorum.

Soyutlama

Soyutlama uygulamak için bir anahtar kelime yoktur fakat mevcut nesne tipi kontrol edilerek ve hata fırlatılarak soyutlama sağlanabilir;

Kod

class Person {
    
    #firstName;
    #lastName;
    #age;
    
    constructor(firstName, lastName, age) {
    
        if(this.constructor == Person){
            throw new Error("Object of Abstract Class cannot be created.");
        }
    
        this.#firstName = firstName;
        this.#lastName = lastName;
        this.#age = age;
    }
    
    // Implementation optional
    getFirstName() {
        return this.#firstName;
    }
    
    // Implementation required
    greet() {
        throw new Error("Abstract Method has no implementation.");
    }
    
}


class Student extends Person{
    
    // Private fields
    #courses;
    
    constructor(firstName, lastName, age, courses) {
        super(firstName, lastName, age)
        
        this.#courses = courses;
    }
    
    // Public function
    getCourses() {
        return this.#courses;
    }
    
    // Abstract Method optional implementation
    getFirstName() {
        return super.getFirstName().toUpperCase();
    }
    
    // Abstract Method implementation    
    greet() {
        return `Merhaba! Benim adım; ${this.getFirstName()}!`;
    }
    
    // Public function
    learn() {
        return `Merhaba! Benim adım; ${super.getFirstName()}! ${this.#courses} derslerini öğreniyorum.`;
    }
    
}


let student = new Student("Altan", "Tekisim", 43, ["Matematik", "Geometri", "Etimoloji"]);



console.log(student);                // Student {#getFullName: ƒ, #firstName: 'Altan', #lastName: 'Tekisim', #age: 43, #courses: Array(3)}
console.log(student.getFirstName());    // ALTAN
console.log(student.greet());            // Merhaba! Benim adım; ALTAN!


let person = new Person("Altan", "Tekisim", 43); // Uncaught Error: Object of Abstract Class cannot be created.

Çok Biçimlilik

Çok Biçimlilik uygulamak için alt sınıfta ilgili fonksiyon aynı isimde yazılır ve içeriği değiştirilir;

Kod


class Person {
    
    // Private fields
    #firstName;
    #lastName;
    #age;
    
    constructor(firstName, lastName, age) {
        this.#firstName = firstName;
        this.#lastName = lastName;
        this.#age = age;
    }
    
    // Public function
    getFirstName() {
        return this.#firstName;
    }
    
    // Public function
    setFirstName(firstName) {
        if(firstName) {
            this.#firstName = firstName;
        }
    }
    
    // Private function
    #getFullName() {
        return `${this.#firstName} ${this.#lastName}`;
    }
    
    // Public function
    greet() {
        return `Merhaba! Benim adım; ${this.#getFullName()}!`;
    }
    
}


class Student extends Person{
    
    // Private fields
    #courses;
    
    constructor(firstName, lastName, age, courses) {
        super(firstName, lastName, age)
        
        this.#courses = courses;
    }
    
    // Public function
    getCourses() {
        return this.#courses;
    }
    
    // Public function
    learn() {
        return `Merhaba! Benim adım; ${super.getFirstName()}! ${this.#courses} derslerini öğreniyorum.`;
    }
    
    // Polymorphism
    greet() {
        return `Merhaba! Ben; ${super.getFirstName().toUpperCase()}, Öğrenciyim!`;
    }
}

let person = new Person("Aydan", "Gelmiş", 30);
let student = new Student("Altan", "Tekisim", 43, ["Matematik", "Geometri", "Etimoloji"]);



console.log(person.greet());            // Merhaba! Benim adım; Aydan Gelmiş!
console.log(student.greet());            // Merhaba! Ben; ALTAN, Öğrenciyim!

Kaynaklar

  1. Object-oriented programming , en.wikipedia.org, 18.02.2023 tarihinde alındı.
  2. Kapsülleme , tr.wikipedia.org, 18.02.2022 tarihinde alındı.
  3. What is object-oriented programming? , techtarget.com, 18.02.2022 tarihinde alındı.
  4. Is JavaScript Object-Oriented? , linuxhint.com, 18.02.2022 tarihinde alındı.
  5. Object Oriented Programming in JavaScript-Explained with Examples , freecodecamp.com, 18.02.2022 tarihinde alındı.
  6. Introduction to Object Oriented Programming in JavaScript , geeksforgeeks.com, 18.02.2022 tarihinde alındı.
  7. Creating objects in JavaScript (4 Different Ways) , geeksforgeeks.com, 18.02.2022 tarihinde alındı.
  8. Understanding encapsulation in JavaScript - See JavaScript encapsulation example , sebhastian.com, 24.02.2022 tarihinde alındı.
  9. Abstraction in JavaScript | Explained , linuxhint.com, 24.02.2022 tarihinde alındı.
  10. Abstract Classes in JavaScript , educba.com, 24.02.2022 tarihinde alındı.
  11. Javascript Abstract Method with ES6 , medium.com/@yuribett, 24.02.2022 tarihinde alındı.
  12. JavaScript Polymorphism , javatpoint.com, 24.02.2022 tarihinde alındı.


Beğen