Takip et

Yapıcılar (Constructors): Nesne Oluşturmanın Temel Taşı

Yapıcılar (Constructors): Nesne Oluşturmanın Temel Taşı Nesne yönelimli programlamanın (NYP) kalbinde, sınıflardan nesneler yaratma ve bu nesneler…

Yapıcılar (Constructors): Nesne Oluşturmanın Temel Taşı

Nesne yönelimli programlamanın (NYP) kalbinde, sınıflardan nesneler yaratma ve bu nesneleri kullanılabilir bir duruma getirme süreci yatar. İşte tam bu noktada yapıcılar, yani “constructors”, devreye girer. Bir sınıfın nesnesi (instance) oluşturulduğunda otomatik olarak çağrılan bu özel metotlar, nesnenin başlangıç durumunu ayarlamak, gerekli kaynakları tahsis etmek ve nesnenin tutarlı bir şekilde hayata başlamasını sağlamak için vazgeçilmez bir rol oynar. Bu makalede, yapıcıların ne olduğunu, neden bu kadar önemli olduklarını, farklı türlerini ve gelişmiş kullanım senaryolarını detaylı bir şekilde inceleyeceğiz.

Yapıcı (Constructor) Nedir?

Yapıcı, bir sınıfın nesnesi oluşturulduğunda otomatik olarak çağrılan özel bir metottur. Temel amacı, yeni oluşturulan nesnenin durumunu (yani üye değişkenlerini) başlatmak ve nesneyi kullanıma hazır hale getirmektir. Her sınıfın en az bir yapıcısı olmak zorundadır; eğer siz bir yapıcı tanımlamazsanız, derleyici sizin için varsayılan bir yapıcı ekler.

Temel Tanım

Bir yapıcı, sınıf adıyla aynı isme sahip olan ve herhangi bir dönüş tipi (void bile) belirtilmeyen bir metottur. Nesneler new anahtar kelimesi kullanılarak oluşturulduğunda, ilgili yapıcı çağrılır. Bu süreç, nesnenin bellekte yer almasını ve başlangıç değerlerinin atanmasını sağlar.

Yapıcıların Özellikleri

Yapıcılar, normal metotlardan farklı bazı özelliklere sahiptir:

  • Sınıf adıyla aynı isme sahiptirler.
  • Dönüş tipi belirtilmez (void bile).
  • new anahtar kelimesiyle nesne oluşturulurken otomatik olarak çağrılırlar.
  • Erişim belirleyicileri (public, private, protected) olabilirler. Genellikle public olurlar ki dışarıdan nesne oluşturulabilsin.

Yapıcı ve Metot Farkı

Yapıcılar ve metotlar arasındaki temel fark, amaçlarıdır. Yapıcılar, nesneleri başlatmak ve ilk durumlarını ayarlamak için kullanılırken, metotlar nesne üzerinde belirli işlemleri gerçekleştirmek veya nesnenin durumunu değiştirmek için kullanılır. Yapıcılar sadece nesne oluşturulurken bir kez çağrılırken, metotlar nesnenin ömrü boyunca istenildiği zaman çağrılabilir.

Yapıcıların Amacı ve Önemi

Yapıcılar, nesne yönelimli programlamada nesnelerin doğru ve güvenli bir şekilde başlatılmasını sağlayarak kritik bir rol oynar. Onlar olmadan, nesneler tutarsız veya eksik bir durumda oluşabilir, bu da çalışma zamanı hatalarına yol açabilir.

Nesne Başlatma

Bir nesne oluşturulduğunda, üye değişkenleri genellikle varsayılan değerlere (sayısal tipler için 0, boolean için false, referans tipleri için null) sahiptir. Yapıcılar, bu varsayılan değerleri, uygulamanın mantığına uygun başlangıç değerleriyle değiştirmek için kullanılır. Örneğin, bir Ogrenci nesnesi oluşturulurken ad, soyad ve ogrenciNo gibi bilgilerin hemen atanması gerekebilir.

Tutarlılık Sağlama

Yapıcılar, bir nesnenin her zaman geçerli ve kullanılabilir bir durumda olmasını garanti eder. Zorunlu alanların boş bırakılmamasını veya geçersiz değerler almasını engelleyebilirler. Bu, programın daha kararlı ve hatasız çalışmasına yardımcı olur.

Kaynak Tahsisi

Bazı durumlarda, bir nesnenin oluşturulmasıyla birlikte dosya tanıtıcıları, ağ bağlantıları veya veritabanı bağlantıları gibi harici kaynakların da tahsis edilmesi gerekebilir. Yapıcılar, bu tür kaynakları nesneyle birlikte başlatmak için uygun bir yer sağlar.

Farklı Yapıcı Türleri

Yapıcılar, aldıkları parametre sayısına ve türüne göre farklılık gösterir. En yaygın kullanılan türler parametresiz ve parametreli yapıcılardır.

Parametresiz Yapıcı (No-Argument Constructor)

Parametresiz yapıcı, adından da anlaşılacağı gibi herhangi bir parametre almayan yapıcıdır. Genellikle nesnenin üye değişkenlerine varsayılan değerler atamak için kullanılır.

public class Kitap {
    String baslik;
    String yazar;
    int sayfaSayisi;

    // Parametresiz Yapıcı
    public Kitap() {
        this.baslik = "Bilinmiyor";
        this.yazar = "Bilinmiyor";
        this.sayfaSayisi = 0;
        System.out.println("Parametresiz Kitap nesnesi oluşturuldu.");
    }

    public void bilgileriGoster() {
        System.out.println("Başlık: " + baslik + ", Yazar: " + yazar + ", Sayfa Sayısı: " + sayfaSayisi);
    }

    public static void main(String[] args) {
        Kitap kitap1 = new Kitap(); // Parametresiz yapıcı çağrılır
        kitap1.bilgileriGoster();
    }
}


Yukarıdaki örnekte, Kitap sınıfının parametresiz yapıcısı, nesne oluşturulduğunda baslik, yazar ve sayfaSayisi alanlarına varsayılan değerler atar.

Parametreli Yapıcı (Parameterized Constructor)

Parametreli yapıcılar, bir veya daha fazla parametre alarak nesne oluşturulurken dışarıdan değerlerin atanmasını sağlar. Bu, nesnenin daha esnek bir şekilde başlatılmasına olanak tanır.

public class Kitap {
    String baslik;
    String yazar;
    int sayfaSayisi;

    // Parametreli Yapıcı
    public Kitap(String baslik, String yazar, int sayfaSayisi) {
        this.baslik = baslik;
        this.yazar = yazar;
        this.sayfaSayisi = sayfaSayisi;
        System.out.println("Parametreli Kitap nesnesi oluşturuldu.");
    }

    public void bilgileriGoster() {
        System.out.println("Başlık: " + baslik + ", Yazar: " + yazar + ", Sayfa Sayısı: " + sayfaSayisi);
    }

    public static void main(String[] args) {
        Kitap kitap2 = new Kitap("Java Programlama", "Ahmet Yılmaz", 500); // Parametreli yapıcı çağrılır
        kitap2.bilgileriGoster();
    }
}


Bu örnekte, Kitap nesnesi oluşturulurken baslik, yazar ve sayfaSayisi doğrudan parametre olarak geçilir ve yapıcı tarafından atanır.

Kopyalama Yapıcısı (Copy Constructor)

Kopyalama yapıcısı, mevcut bir nesnenin durumunu kullanarak yeni bir nesne oluşturan özel bir yapıcı türüdür. Özellikle C++ gibi dillerde yaygın olarak kullanılırken, Java'da doğrudan bir "kopyalama yapıcısı" kavramı yoktur. Bunun yerine, genellikle mevcut nesneyi parametre olarak alan bir yapıcı tanımlanır veya bir clone() metodu kullanılır.

public class Kitap {
    String baslik;
    String yazar;
    int sayfaSayisi;

    public Kitap(String baslik, String yazar, int sayfaSayisi) {
        this.baslik = baslik;
        this.yazar = yazar;
        this.sayfaSayisi = sayfaSayisi;
    }

    // Kopyalama Yapıcısı (Java stilinde)
    public Kitap(Kitap digerKitap) {
        this.baslik = digerKitap.baslik;
        this.yazar = digerKitap.yazar;
        this.sayfaSayisi = digerKitap.sayfaSayisi;
        System.out.println("Bir Kitap nesnesi kopyalanarak oluşturuldu.");
    }

    public void bilgileriGoster() {
        System.out.println("Başlık: " + baslik + ", Yazar: " + yazar + ", Sayfa Sayısı: " + sayfaSayisi);
    }

    public static void main(String[] args) {
        Kitap orijinalKitap = new Kitap("Veri Yapıları", "Ayşe Demir", 350);
        orijinalKitap.bilgileriGoster();

        Kitap kopyaKitap = new Kitap(orijinalKitap); // Kopyalama yapıcısı çağrılır
        kopyaKitap.bilgileriGoster();
    }
}


Bu örnekte, Kitap(Kitap digerKitap) yapıcısı, mevcut bir Kitap nesnesinin değerlerini alarak yeni bir Kitap nesnesi oluşturur.

Yapıcı Overloading (Aşırı Yükleme)

Yapıcı aşırı yükleme (constructor overloading), bir sınıfta birden fazla yapıcı tanımlama yeteneğidir. Bu yapıcıların her birinin parametre listesi (parametre sayısı, parametre tipleri veya parametre sıralaması) farklı olmalıdır. Bu sayede, nesneler farklı başlangıç durumlarıyla veya farklı veri setleriyle oluşturulabilir.

Tanım

Aşırı yükleme, aynı isimde birden fazla metot (veya yapıcı) tanımlamanın genel bir kavramıdır. Yapıcılar için bu, bir sınıfın, nesnelerinin oluşturulma şekli için birden fazla seçenek sunması anlamına gelir.

Kullanım Alanları

Yapıcı aşırı yükleme, bir nesnenin farklı senaryolarda farklı şekillerde başlatılması gerektiğinde çok kullanışlıdır. Örneğin, bir Ogrenci nesnesi bazen sadece isimle, bazen isim ve numarayla, bazen de tüm detaylarla oluşturulmak istenebilir.

Örnek Senaryo

Bir Ogrenci sınıfı için farklı yapıcılar tanımlayarak aşırı yüklemeyi gösterelim:

public class Ogrenci {
    String ad;
    String soyad;
    int ogrenciNo;
    String bolum;

    // 1. Parametresiz Yapıcı
    public Ogrenci() {
        this.ad = "Bilinmiyor";
        this.soyad = "Bilinmiyor";
        this.ogrenciNo = 0;
        this.bolum = "Bilinmiyor";
        System.out.println("Varsayılan Ogrenci nesnesi oluşturuldu.");
    }

    // 2. Sadece isim ve soyad alan yapıcı
    public Ogrenci(String ad, String soyad) {
        this.ad = ad;
        this.soyad = soyad;
        this.ogrenciNo = 0; // Varsayılan değer
        this.bolum = "Bilinmiyor"; // Varsayılan değer
        System.out.println("İsim ve soyad ile Ogrenci nesnesi oluşturuldu.");
    }

    // 3. Tüm bilgileri alan yapıcı
    public Ogrenci(String ad, String soyad, int ogrenciNo, String bolum) {
        this.ad = ad;
        this.soyad = soyad;
        this.ogrenciNo = ogrenciNo;
        this.bolum = bolum;
        System.out.println("Tüm bilgilerle Ogrenci nesnesi oluşturuldu.");
    }

    public void bilgileriGoster() {
        System.out.println("Ad: " + ad + ", Soyad: " + soyad + ", No: " + ogrenciNo + ", Bölüm: " + bolum);
    }

    public static void main(String[] args) {
        Ogrenci ogrenci1 = new Ogrenci();
        ogrenci1.bilgileriGoster();

        Ogrenci ogrenci2 = new Ogrenci("Elif", "Kara");
        ogrenci2.bilgileriGoster();

        Ogrenci ogrenci3 = new Ogrenci("Can", "Yılmaz", 101, "Bilgisayar Mühendisliği");
        ogrenci3.bilgileriGoster();
    }
}


Bu örnekte, Ogrenci sınıfı, farklı parametre listelerine sahip üç farklı yapıcıya sahiptir. Bu, geliştiricilere Ogrenci nesnelerini farklı ihtiyaçlara göre başlatma esnekliği sunar.

Varsayılan Yapıcı (Default Constructor) ve Parametresiz Yapıcı

Bu iki kavram sıklıkla karıştırılsa da, aralarında önemli bir fark vardır. Her ikisi de parametre almaz, ancak nasıl ve ne zaman ortaya çıktıkları farklıdır.

Varsayılan Yapıcı Nedir?

Eğer bir sınıfta hiçbir yapıcı (parametreli veya parametresiz) tanımlanmamışsa, Java derleyicisi otomatik olarak herkese açık (public) ve parametresiz, boş bir yapıcı ekler. Buna "varsayılan yapıcı" denir. Bu yapıcı, sınıfın üye değişkenlerine varsayılan değerlerini atar (sayısal tipler için 0, boolean için false, referans tipleri için null).

Ne Zaman Oluşturulur?

Varsayılan yapıcı, yalnızca ve yalnızca geliştirici tarafından hiçbir yapıcı tanımlanmadığında derleyici tarafından oluşturulur. Eğer siz kendi parametreli veya parametresiz yapıcınızı tanımlarsanız, derleyici artık otomatik olarak varsayılan yapıcıyı eklemez.

Varsayılan Yapıcının Davranışı

Varsayılan yapıcı, hiçbir özel başlatma kodu içermez. Sadece üst sınıfın parametresiz yapıcısını çağırır (super()) ve üye değişkenlerinin varsayılan değerleriyle kalmasını sağlar.

Parametresiz Yapıcı ile Farkı

Özellik Varsayılan Yapıcı (Default Constructor) Parametresiz Yapıcı (No-Argument Constructor)
Oluşturan Java Derleyicisi Geliştirici
Ne Zaman Ortaya Çıkar Sınıfta hiçbir yapıcı tanımlanmadığında Geliştirici tarafından açıkça tanımlandığında
Amaç Nesne oluşturmayı sağlamak (minimum başlatma) Nesneye özel varsayılan değerler atamak
Örnek public SınıfAdı() {} (derleyici tarafından eklenir) public SınıfAdı() { this.deger = "varsayılan"; } (geliştirici yazar)

this Anahtar Kelimesi ve Yapıcılar

this anahtar kelimesi, Java'da mevcut nesnenin bir referansını temsil eder. Yapıcılar içinde iki ana amaçla kullanılır: üye değişkenlerini parametrelerden gelen değerlerle ayırmak ve bir yapıcının başka bir yapıcıyı çağırmasını sağlamak.

this Referansı

Bir yapıcıda, parametre isimleri ile sınıfın üye değişkenlerinin isimleri aynı olduğunda belirsizlik oluşabilir. this anahtar kelimesi, sınıfın üye değişkenini belirtmek için kullanılırken, parametre doğrudan ismini kullanarak erişilir.

public class Urun {
    String ad;
    double fiyat;

    public Urun(String ad, double fiyat) {
        this.ad = ad;   // 'this.ad' sınıfın üye değişkeni 'ad'i ifade eder.
        this.fiyat = fiyat; // 'fiyat' ise parametreden gelen değeri ifade eder.
    }

    public void bilgileriGoster() {
        System.out.println("Ürün Adı: " + ad + ", Fiyat: " + fiyat);
    }

    public static void main(String[] args) {
        Urun urun = new Urun("Klavye", 150.75);
        urun.bilgileriGoster();
    }
}


Yukarıdaki örnekte, this.ad ve this.fiyat kullanılarak sınıfın ad ve fiyat üye değişkenleri, yapıcıya gelen ad ve fiyat parametreleriyle başlatılır.

Yapıcıdan Başka Bir Yapıcıyı Çağırma (this())

this() ifadesi, bir yapıcıdan aynı sınıfın başka bir yapıcısını çağırmak için kullanılır. Bu, yapıcı aşırı yüklemesi durumunda kod tekrarını önlemek ve daha temiz, daha sürdürülebilir kod yazmak için harika bir yoldur. this() çağrısı, yapıcının ilk ifadesi olmak zorundadır.

public class Calisan {
    String ad;
    int id;
    double maas;

    // Tam parametreli yapıcı
    public Calisan(String ad, int id, double maas) {
        this.ad = ad;
        this.id = id;
        this.maas = maas;
        System.out.println("Tüm bilgilerle çalışan oluşturuldu.");
    }

    // Sadece ad ve id alan yapıcı, tam parametreli yapıcıyı çağırır
    public Calisan(String ad, int id) {
        this(ad, id, 0.0); // Diğer yapıcıyı çağırır (maas varsayılan olarak 0.0 atanır)
        System.out.println("Ad ve ID ile çalışan oluşturuldu.");
    }

    // Sadece ad alan yapıcı, ad ve id alan yapıcıyı çağırır
    public Calisan(String ad) {
        this(ad, 0); // Diğer yapıcıyı çağırır (id varsayılan olarak 0 atanır)
        System.out.println("Sadece ad ile çalışan oluşturuldu.");
    }

    public void bilgileriGoster() {
        System.out.println("Ad: " + ad + ", ID: " + id + ", Maaş: " + maas);
    }

    public static void main(String[] args) {
        Calisan c1 = new Calisan("Ayşe");
        c1.bilgileriGoster();

        Calisan c2 = new Calisan("Mehmet", 101);
        c2.bilgileriGoster();

        Calisan c3 = new Calisan("Zeynep", 102, 7500.0);
        c3.bilgileriGoster();
    }
}


Bu örnekte, daha az parametre alan yapıcılar, daha fazla parametre alan yapıcıları çağırarak kod tekrarını önler ve varsayılan değerlerin atanmasını kolaylaştırır.

Yapıcı Zincirleme (Constructor Chaining)

Yapıcı zincirleme, bir yapıcının, aynı sınıfın veya üst sınıfın başka bir yapıcısını çağırma işlemidir. Bu mekanizma, kod tekrarını azaltır ve nesne başlatma mantığını daha düzenli hale getirir.

Tanım

Yapıcı zincirleme, bir yapıcının başlatma görevini kısmen veya tamamen başka bir yapıcıya devretmesidir. Bu, özellikle karmaşık nesne hiyerarşilerinde veya çok sayıda aşırı yüklenmiş yapıcıya sahip sınıflarda faydalıdır.

Faydaları

  • Kod Tekrarını Azaltma: Ortak başlatma mantığını tek bir yapıcıda toplar ve diğer yapıcıların bu ana yapıcıyı çağırmasını sağlar.
  • Modülerlik: Her yapıcı kendi özel başlatma görevini yerine getirirken, genel başlatma mantığı tek bir yerde korunur.
  • Okunabilirlik ve Bakım Kolaylığı: Kodun daha temiz ve anlaşılır olmasını sağlar, hataları bulmayı ve düzeltmeyi kolaylaştırır.

İki Tür Zincirleme

Yapıcı zincirleme iki ana şekilde gerçekleşebilir:

Aynı Sınıf İçinde Zincirleme (this())

Daha önce this anahtar kelimesi bölümünde ele aldığımız gibi, this() ifadesi aynı sınıfın başka bir yapıcısını çağırmak için kullanılır. Bu, aşırı yüklenmiş yapıcılar arasında ortak başlatma mantığını paylaşmanın en yaygın yoludur.

Üst Sınıf Yapıcısını Zincirleme (super())

Kalıtım durumunda, alt sınıfın yapıcısı, üst sınıfın (ebeveyn sınıfın) yapıcısını super() anahtar kelimesini kullanarak çağırabilir. Bu, alt sınıf nesnesi oluşturulmadan önce üst sınıfın başlatma mantığının yürütülmesini sağlar. super() çağrısı da yapıcının ilk ifadesi olmak zorundadır.

class Kisi {
    String isim;
    int yas;

    public Kisi(String isim, int yas) {
        this.isim = isim;
        this.yas = yas;
        System.out.println("Kisi nesnesi oluşturuldu.");
    }

    public void bilgileriGoster() {
        System.out.println("İsim: " + isim + ", Yaş: " + yas);
    }
}

class Ogrenci extends Kisi {
    String okulNo;

    public Ogrenci(String isim, int yas, String okulNo) {
        super(isim, yas); // Üst sınıfın (Kisi) yapıcısını çağırır
        this.okulNo = okulNo;
        System.out.println("Ogrenci nesnesi oluşturuldu.");
    }

    @Override
    public void bilgileriGoster() {
        super.bilgileriGoster(); // Üst sınıfın metodunu çağırır
        System.out.println("Okul No: " + okulNo);
    }

    public static void main(String[] args) {
        Ogrenci ogrenci = new Ogrenci("Deniz", 20, "12345");
        ogrenci.bilgileriGoster();
    }
}


Bu örnekte, Ogrenci sınıfının yapıcısı, super(isim, yas) kullanarak Kisi sınıfının yapıcısını çağırır. Bu, isim ve yas alanlarının Kisi yapıcısı tarafından başlatılmasını sağlar ve Ogrenci yapıcısının sadece kendi özel alanı olan okulNo'yu başlatması yeterli olur.

Sonuç

Yapıcılar, nesne yönelimli programlamanın temel taşlarından biridir. Nesnelerin yaşam döngüsünün başında, yani oluşturulma anında, doğru ve tutarlı bir şekilde başlatılmalarını sağlayarak, programların güvenilirliğini ve kararlılığını artırırlar. Parametresiz, parametreli, aşırı yüklenmiş yapıcılar ve this(), super() gibi mekanizmalar sayesinde geliştiriciler, nesne başlatma süreçlerini esnek, modüler ve kod tekrarından arındırılmış bir şekilde yönetebilirler. Yapıcıların doğru anlaşılması ve etkin kullanımı, daha temiz, daha okunabilir ve daha sürdürülebilir yazılım geliştirmek için kritik öneme sahiptir.

Sıkça Sorulan Sorular (SSS)

Yapıcılar neden dönüş tipi belirtmez?

Yapıcılar, bir değer döndürmek yerine, yeni oluşturulan nesnenin kendisini başlatır. Bu nedenle, açıkça bir dönüş tipi (void bile) belirtmeye gerek yoktur. Zaten new anahtar kelimesiyle çağrıldıklarında, ilgili sınıfın bir nesnesini döndürürler.

Bir sınıfın birden fazla yapıcısı olabilir mi?

Evet, yapıcı aşırı yükleme (constructor overloading) sayesinde bir sınıfın birden fazla yapıcısı olabilir. Her bir yapıcının parametre listesi (parametre sayısı, tipleri veya sıralaması) farklı olmalıdır.

Varsayılan yapıcıyı ne zaman kaybederiz?

Eğer bir sınıfta kendi parametreli veya parametresiz yapıcınızı açıkça tanımlarsanız, Java derleyicisi artık sizin için otomatik olarak varsayılan yapıcıyı eklemez. Bu durumda, parametresiz

Yorumlar
İçeriği beğendiniz mi? Bir tartışma başlatın veya görüşlerinizi paylaşın.
Yorum Yaz

Bir yanıt yazın

E-posta adresiniz yayınlanmayacak. Gerekli alanlar * ile işaretlenmişlerdir

E-posta Bülteni
Yazılım Topluluğuna Katılın
En son güncellemeleri, yaratıcı ipuçlarını ve özel kaynakları doğrudan e-posta kutunuza alın. Tasarım ve inovasyonun geleceğini birlikte keşfedelim.