JavaScript ve Nesne Tabanlı Programlama

 JavaScript ve Nesne Tabanlı Programlama
Okunuyor JavaScript ve Nesne Tabanlı Programlama

Bu makale, nesne yönelimli programlama (OOP) konusunda önceden bilgisi olmayan JavaScript öğrencileri için yazılmıştır. OOP’nin yalnızca JavaScript ile ilgili olan ve genel olarak OOP ile ilgili olmayan kısımlarına odaklanıyorum. Polimorfizmi atlıyorum çünkü statik tipli bir dile daha iyi uyuyor

javascript

İçindekiler

Bunu neden bilmen gerekiyor?

İlk programlama diliniz olarak JavaScript’i seçtiniz mi? Yüz bin veya daha fazla satırlık kod içeren dev kurumsal sistemlerde çalışan başarılı bir geliştirici olmak ister misiniz?

Nesne Yönelimli Programlamayı tam olarak benimsemeyi öğrenmezseniz, iyi ve gerçekten kaybolacaksınız.

Farklı Zihniyetler

Futbolda güvenli bir savunmadan oynayabilir, yanlardan yüksek toplarla oynayabilirsiniz veya yarın yokmuş gibi hücum yapabilirsiniz. Tüm bu stratejilerin amacı aynı: Oyunu kazanmak.

Aynısı programlama paradigmaları için de geçerlidir. Bir soruna yaklaşmanın ve bir çözüm tasarlamanın farklı yolları vardır.

Nesne yönelimli programlama veya OOP, modern uygulama geliştirme paradigmasıdır ve Java, C # veya JavaScript gibi ana diller tarafından desteklenir.

Nesne Tabanlı Paradigma

OOP perspektifinden, bir uygulama birbiriyle iletişim kuran “nesneler” koleksiyonudur. Bu nesneleri, envanterdeki veya çalışan kayıtlarındaki ürünler gibi gerçek dünyadaki şeylere dayandırıyoruz. Nesneler veri içerir ve verilerine dayanarak bazı mantık yürütür. Sonuç olarak, OOP kodunu anlamak çok kolaydır. O kadar kolay olmayan şey, ilk olarak bir uygulamanın bu küçük nesnelere nasıl bölüneceğine karar vermektir.

İlk kez duyduğumda benim gibiyseniz, bunun gerçekte ne anlama geldiğine dair hiçbir fikriniz yok – hepsi kulağa çok soyut geliyor. Böyle hissetmek kesinlikle iyidir. Fikri duymanız, hatırlamanız ve kodunuza OOP uygulamayı denemeniz daha önemlidir. Zamanla, deneyim kazanacak ve kodunuzun daha fazlasını bu teorik konseptle uyumlu hale getireceksiniz.

Ders : Gerçek dünya nesnelerine dayalı OOP, herkesin kodunuzu okumasına ve neler olduğunu anlamasına olanak tanır.

Merkez parçası olarak nesne

Merkez parçası olarak nesne

Basit bir örnek, JavaScript’in OOP’nin temel ilkelerini nasıl uyguladığını görmenize yardımcı olacaktır. Ürünleri sepetinize koyduğunuz bir alışveriş kullanım durumunu düşünün ve ardından ödemeniz gereken toplam fiyatı hesaplayın. JavaScript bilginizi alır ve kullanım senaryosunu OOP olmadan kodlarsanız, aşağıdaki gibi görünür:

const bread = {name: 'Bread', price: 1};
const water = {name: 'Water', price: 0.25};
 
const basket = [];
basket.push(bread);
basket.push(bread);
basket.push(water);
basket.push(water);
basket.push(water);
 
const total = basket
  .map(product => product.price)
  .reduce((a, b) => a + b, 0);
 
console.log('one has to pay in total: ' + total);

OOP perspektifi, daha iyi kod yazmayı kolaylaştırır çünkü nesneleri gerçek dünyada karşılaştığımız gibi düşünürüz. Kullanım durumumuz bir ürün sepeti içerdiğinden, halihazırda iki tür nesneye sahibiz – sepet nesnesi ve ürün nesneleri.

Alışveriş kullanım senaryosunun OOP sürümü şu şekilde yazılabilir:

const bread = new Product("bread", 1);
const water = new Product("water", .25)
 
const basket = new Basket();
basket.addProduct(2, bread);
basket.addProduct(3, water);
basket.printShoppingInfo();

İlk satırda görebileceğiniz gibi, anahtar kelimeyi ve newardından sınıf denen şeyin adını (aşağıda açıklanmıştır) kullanarak yeni bir nesne oluşturuyoruz . Bu, ekmeği değişkene sakladığımız bir nesneyi döndürür. Bunu değişken su için tekrarlıyoruz ve değişken bir sepet oluşturmak için benzer bir yol izliyoruz. Bu ürünleri sepetinize ekledikten sonra, sonunda ödemeniz gereken toplam tutarı yazdırırsınız.

İki kod parçacığı arasındaki fark açıktır. OOP sürümü neredeyse gerçek İngilizce cümleler gibi okur ve neler olup bittiğini kolayca anlayabilirsiniz.

Ders : Gerçek dünyadaki şeyler üzerine modellenen bir nesne, veriler ve işlevlerden oluşur.

Şablon olarak Sınıf
Şablon olarak Sınıf

Nesne oluşturmak için şablon olarak OOP’ta sınıfları kullanıyoruz. Bir nesne, bir “sınıfın örneği” ve “somutlaştırma”, bir sınıfa dayalı bir nesnenin oluşturulmasıdır. Kod sınıfta tanımlanır ancak canlı bir nesnede olmadığı sürece yürütülemez.

Bir arabanın planları gibi sınıflara bakabilirsiniz. Otomobilin tork ve beygir gücü gibi özelliklerini, hava-yakıt oranları gibi dahili işlevleri ve ateşleme gibi halka açık yöntemleri tanımlarlar. Sadece bir fabrika otomobili örneklediğinde, ancak anahtarı çevirip sürebilirsiniz.

Kullanım durumumuzda, iki nesneyi, ekmek ve suyu somutlaştırmak için Product sınıfını kullanırız. Tabii ki, bu nesnelerin sınıflarda sağlamanız gereken koda ihtiyaçları vardır. Bu böyle devam ediyor:

function Product(_name, _price) {
  const name = _name;
  const price = _price;
 
  this.getName = function() {
    return name;
  };
 
  this.getPrice = function() {
    return price;
  };
}
 
function Basket() {
  const products = [];
 
  this.addProduct = function(amount, product) {
    products.push(...Array(amount).fill(product));
  };
 
  this.calcTotal = function() {
    return products
      .map(product => product.getPrice())
      .reduce((a, b) => a + b, 0);
  };
 
  this.printShoppingInfo = function() {
    console.log('one has to pay in total: ' + this.calcTotal());
  };
}

JavaScript’teki bir sınıf bir işleve benziyor, ancak siz onu farklı şekilde kullanıyorsunuz. İşlevin adı, sınıfın adıdır ve büyük harfle yazılmıştır. Hiçbir şey döndürmediğinden, işlevi her zamanki gibi çağırmıyoruz const basket = Product("bread", 1);. Bunun yerine, yeni gibi anahtar kelimesini ekliyoruz const basket = new Product("bread", 1);.

İşlevin içindeki kod yapıcıdır ve bir nesnenin somutlaştırıldığı her seferde çalıştırılır. Ürün parametreleri _name ve _price. Her yeni nesne bu değerleri içinde saklar.

Ayrıca nesnenin sağlayacağı fonksiyonları da tanımlayabiliriz. Bu işlevi this , onları dışarıdan erişilebilir kılan anahtar kelimeyi önceden belirleyerek tanımlarız (bkz. Kapsülleme). İşlevlerin özelliklere tam erişime sahip olduğuna dikkat edin.

Sınıf Sepeti, yeni bir nesne oluşturmak için herhangi bir bağımsız değişken gerektirmez. Yeni bir Basket nesnesi oluşturmak, programın daha sonra doldurabileceği boş bir ürün listesi oluşturur.

Ders : Sınıf, çalışma süresi sırasında nesne oluşturmak için kullanılan bir şablondur.

Kapsülleme

Bir sınıfı nasıl ilan edeceğinizin başka bir versiyonuyla karşılaşabilirsiniz:

function Product(name, price) {
  this.name = name;
  this.price = price;
}

Özelliklerin değişkene atanmasına dikkat edin this. İlk bakışta daha iyi bir sürüm gibi görünüyor çünkü artık alıcı (getName & getPrice) yöntemlerini gerektirmiyor ve bu nedenle daha kısa.

Ne yazık ki, artık mülklere dışarıdan tam erişim verdiniz. Böylece herkes ona erişebilir ve değiştirebilir:

const bread = new Product('bread', 1)
bread.price = -10;

Bu, uygulamanın bakımını daha zor hale getirdiği için istemediğiniz bir şeydir. Örneğin sıfırdan düşük fiyatları önlemek için doğrulama kodu eklerseniz ne olur? Price özelliğine doğrudan erişen herhangi bir kod, doğrulamayı atlayacaktır. Bu, izlenmesi zor olan hatalara neden olabilir. Öte yandan, nesnenin alıcı yöntemlerini kullanan kodun, nesnenin fiyat doğrulamasından geçmesi garanti edilir.

Nesneler, verileri üzerinde özel kontrole sahip olmalıdır. Başka bir deyişle, nesneler verilerini “sarmalar” ve diğer nesnelerin verilere doğrudan erişmesini engeller. Verilere erişmenin tek yolu dolaylı olarak nesnelere yazılan işlevlerdir.

Veri ve işleme (diğer adıyla mantık) birbirine aittir. Bu, özellikle verilerin işlenmesinin özel olarak tanımlanmış yerlerle sınırlandırılmasının çok önemli olduğu daha büyük uygulamalar söz konusu olduğunda geçerlidir.

Doğru yapıldığında, sonuç OOP tasarımla modülerlik, yazılım geliştirmede kutsal kâse üretir. Her şeyin birbirine sıkı sıkıya bağlı olduğu ve küçük bir kod parçasını değiştirdiğinizde ne olacağını bilmediğiniz korkulan spagetti kodunu uzak tutar.

Bizim durumumuzda, Ürün sınıfının nesneleri, başlatıldıktan sonra fiyatı veya adı değiştirmenize izin vermez. Ürün örnekleri salt okunurdur.

Ders : Kapsülleme, nesnenin işlevleri dışında verilere erişimi engeller.

Miras

Devralma, mevcut bir sınıfı ek özellikler ve işlevlerle genişleterek yeni bir sınıf oluşturmanıza olanak tanır. Yeni sınıf, yeni kodun sıfırdan oluşturulmasını önleyerek, üst sınıfının tüm özelliklerini “devralır”. Ayrıca, ebeveyn sınıfında yapılan herhangi bir değişiklik otomatik olarak alt sınıfın kullanımına sunulacak ve bu da güncellemeleri çok daha kolay hale getirecektir.

Kitap adında adı, fiyatı ve yazarı olan yeni bir sınıfımız olduğunu varsayalım. Miras ile, bir Kitabın bir Ürün ile aynı olduğunu ancak ek yazar özelliğine sahip olduğunu söyleyebilirsiniz. Ürün’ün Kitabın üst sınıfı olduğunu ve Kitap’ın bir Ürün alt sınıfı olduğunu söylüyoruz:

function Book(_name, _price, _author) {
  Product.call(this, _name, _price);
  const author = _author;
 
  this.getAuthor = function() {
    return author;
  }
}

İlk argüman Product.callboyunca eki not edin this. Lütfen unutmayın: Kitap, alıcı yöntemleri sağlasa da, yine de mülklerin adına ve fiyatına doğrudan erişime sahip değildir. Kitap, bu verileri Ürün sınıfından çağırmalıdır.
Artık herhangi bir sorun olmadan sepete bir kitap nesnesi ekleyebilirsiniz:

const faust = new Book('faust', 12.5, 'Goethe');
basket.addProduct(1, faust);

Sepet, Ürün türünde bir nesne bekler ve kitap, Kitap aracılığıyla Ürün’den devraldığı için, aynı zamanda bir Üründür.

Ders : Alt sınıflar, kendi özelliklerini ve işlevlerini eklerken üst sınıflardan özellikleri ve işlevleri devralabilir.

JavaScript ve OOP

JavaScript uygulamaları oluşturmak için kullanılan üç farklı programlama paradigması bulacaksınız. Prototip Tabanlı Programlama, Nesne Tabanlı Programlama ve Fonksiyonel Yönelimli Programlamadır.

Bunun nedeni JavaScript’in geçmişinde yatmaktadır. Başlangıçta prototip tabanlıydı. JavaScript, büyük uygulamalar için bir dil olarak tasarlanmamıştır.

Kurucularının planının aksine, geliştiriciler daha büyük uygulamalar için JavaScript’i giderek daha fazla kullandı. OOP, orijinal prototip tabanlı tekniğin üzerine aşılanmıştır.

Prototip tabanlı yaklaşım aşağıda gösterilmektedir ve sınıfları oluşturmanın “klasik ve varsayılan yolu” olarak görülmektedir. Maalesef kapsüllemeyi desteklemiyor.

JavaScript’in OOP desteği, Java gibi diğer dillerle aynı seviyede olmasa da, hala gelişmektedir. ES6 sürümünün yayınlanması, class kullanabileceğimiz özel bir anahtar kelime ekledi . Dahili olarak, prototip özelliği ile aynı amaca hizmet eder, ancak kodun boyutunu azaltır. Bununla birlikte, ES6 sınıfları hala özel mülklerden yoksundur, bu yüzden “eski yola” bağlı kaldım.

Eksiksizlik adına Ürün, Sepet ve Kitabı ES6 sınıfları ve ayrıca prototip (klasik ve varsayılan) yaklaşımıyla böyle yazacağız. Lütfen bu sürümlerin kapsülleme sağlamadığını unutmayın:

// ES6 version
 
class Product {
  constructor(name, price) {
    this.name = name;
    this.price = price;
  }
}
 
class Book extends Product {
  constructor(name, price, author) {
    super(name, price);
    this.author = author;
  }
}
 
class Basket {
  constructor() {
    this.products = [];
  }
 
  addProduct(amount, product) {
    this.products.push(...Array(amount).fill(product));
  }
 
  calcTotal() {
    return this.products
      .map(product => product.price)
      .reduce((a, b) => a + b, 0);
  }
 
  printShoppingInfo() {
    console.log('one has to pay in total: ' + this.calcTotal());
  }
}
 
const bread = new Product('bread', 1);
const water = new Product('water', 0.25);
const faust = new Book('faust', 12.5, 'Goethe');
 
const basket = new Basket();
basket.addProduct(2, bread);
basket.addProduct(3, water);
basket.addProduct(1, faust);
basket.printShoppingInfo();
//Prototype version
 
function Product(name, price) {
  this.name = name;
  this.price = price;
}
 
function Book(name, price, author) {
  Product.call(this, name, price);
  this.author = author;
}
Book.prototype = Object.create(Product.prototype);
Book.prototype.constructor = Book;
 
function Basket() {
  this.products = [];
}
Basket.prototype.addProduct = function(amount, product) {
  this.products.push(...Array(amount).fill(product));
};
Basket.prototype.calcTotal = function() {
  return this.products
    .map(product => product.price)
    .reduce((a, b) => a + b, 0);
};
Basket.prototype.printShoppingInfo = function() {
  console.log('one has to pay in total: ' + this.calcTotal());
};

Ders : OOP, geliştirilmesinin sonraki aşamalarında JavaScript’e eklendi.

Özet

JavaScript öğrenen yeni bir programcı olarak, Nesne Tabanlı Programlamayı tamamen takdir etmek zaman alacaktır. Bu erken aşamada anlaşılması gereken önemli şeyler, OOP paradigmasının dayandığı ilkeler ve sağladıkları faydalardır:

  • Gerçek dünyadaki şeylere göre modellenen nesneler, OOP tabanlı uygulamaların merkezinde yer alır.
  • Kapsülleme, verileri kontrolsüz erişime karşı korur.
  • Nesnelerin, nesnelerin içerdiği veriler üzerinde çalışan işlevleri vardır.
  • Sınıflar, nesneleri somutlaştırmak için kullanılan şablonlardır.
  • Kalıtım, fazlalıktan kaçınmak için güçlü bir araçtır.
  • OOP daha ayrıntılıdır ancak diğer kodlama paradigmalarına göre okunması daha kolaydır.
  • OOP, JavaScript’in geliştirilmesinde daha sonra geldiğinden, prototip veya işlevsel programlama tekniklerini kullanan eski kodlarla karşılaşabilirsiniz.
daha fazla okuma

Umarım yazım sizler için faydalı olmuştur. Birbirinden farklı konulardaki yazılarımız için sayfamızı ziyaret edebilirsiniz. Sağlıcakla kalın..

Yorum Yap