Kubilay Kahil
YazarKubilay Kahil
16 dakika okuma süresi
Eki 22, 2019

JAVA OOP Temelleri


Kaynak Hakkında

  Bu eğitim dökümanı JAVA’da nesne yönelimli programlama temellerini öğretebilmek amacıyla hazırlanmıştır, sıfırdan JAVA öğrenimi gerçekleştirmek için uygun bir kaynak değildir. JAVA’da fonksiyonel işlemleri öğrendikten sonra veya farklı bir dilde fonksiyonel programlama mantığını anlayınca, nesne yönelimli programlamaya bir temel oluşturacaktır. OOP mantığının oturabilmesi için, github kaynaklı örnekler vermeye çalıştım. Dökümanı incelerken, bir yandan da IDE üzerinde aynı örneği uygulamaya çalışın. Örneklerle sınırlı kalmayıp, kendi mantığınız ile yorumlayarak örnekler tasarlamanız pekiştirmeniz açısından kolaylık sağlayacaktır.

İçindekiler

İşin Felsefesi

Nesnelerin Özellikleri

Nesnelerin Davranışları (methodları)

Class Mantığı

Constructor (İnşaatçı, Yapıcı) Yapısı

Nesne Yönelimli Programlamanın Dört Temel Prensibi

Abstraction (Soyutlama)

Encapsulation (Kapsülleme) Prensibi

Inheritance (Kalıtım, Miras Kalma) Prensibi

Polymorphism (Çok Biçimlilik, Çok Şekillilik) Prensibi

İşin Felsefesi

  Daha önce bir programlama diline hafif de olsa giriş yaptıysanız, fonksiyonel programlama ile uğraşmışsınızdır. Nesne yönelimli programlama, fonksiyonel programlama yapısından farklı bir anlayıştır. Bu anlayış, etrafımızda bulunan bütün varlıkların nesne olarak tanımlayabildiğimiz bir programlama yapısı oluşturur. Bunun sonucunda insan diline daha yakın bir yapı kurmamızı sağladığı gibi kodlara daha kolay müdahale edebilmemizi olanak tanır.

  Masa, sandalye, kedi, insan nesne olarak verilebilecek örneklerden sadece bir kısmı. Bu örnekler etramızda bulunan her şeyin eklenmesiyle koca bir küme haline geliyor.

Nesnelerin Özellikleri

  Her nesne özelliklere sahiptir. Bir kedinin siyah renkte olması, kedinin özelliğidir. Özelliği kendisine has olmakla birlikte içerisinde bulunduğu türe özgü olabilir. Kedinin siyah renkte olma özelliği, başka kedilerin siyah olmayacağı veya siyah renk özelliğine sahip olacakları anlamına gelmez.

  Kedimiz bir isme sahip olabilir. Tarçın adını verelim :) İsminin Tarçın olması bir özelliktir. Tarçın oyun oynamayı sevebilir. Oyun oynamayı sevmesi özelliktir. Ancak oyun oynayabiliyor olması bir özellik değildir.

Nesnelerin Davranışları (methodları)

  Tarçın’ın oyun oynamayı sevdiğini söyledik. Oyun oynaması bir davranıştır. Yürümesi, zıplaması, ses çıkarması birer davranıştır. Nesnelerin özelliklerinde olduğu gibi, davranışları da kendisine özgü veya bulundukları türlerle birlikte aynı davranışa sahip olabilir.

  Ayırt edici olabilmesi için: isimler özellik, fiiller davranış olarak kodlanabilir.

Nesnemizin özellik ve davranışlarını birbirleri ile ilişkilendirip, özelliklerine göre davranışlar sergilemesini sağlayabiliriz. Tarçın’ın karnı tok ise, oyun oynasın; Karnı tok değilse, yemek yesin gibi davranışları kurduğumuz yapı içerisinde oluşturabiliriz. Aşağıdaki tabloyu inceleyip, kendiniz de etrafınızdaki nesnelerin özellik ve davranışlarını yazmayı deneyebilirsiniz.

https://gist.github.com/kahilkubilay/f7eeb6f3a1ded7d75d6178e85fd0fc9e#file-gistfile1-txt

Class Mantığı

  Class nesnemizin kapsamını belirten, içerisinde özellik ve davranışları tanımladığımız methodlardır. Class temsil ettiği nesneye göre bir isim alır. Main methodumuz içerisinde class çağırarak, nesnemizi yaşayabilir bir nesne haline dönüştüreceğiz. Nesnemizin canlı bir varlığa dönüşmesi program akışımızda nesneyi kullandığımızı ve artık RAM üzerinde bir alan kapladığı anlamına gelir.

Elleri Kirtletme Vakti

  Class mantığı, nesnenin özellik ve davranışlarına teorik bir bakış attık. Artık bu mantık ile kodlara dökerek gerçek kullanımlarını inceleyelim. İlk örneğimizde adım adım göstermeye çalışacağım. Sonraki örnekleri toplu olarak yazıp, açıklama yapmaya çalışacağım.

  Class oluşturmak için farklı bir dosya açabileceğimiz gibi, main dosyasının bulunduğu dosya içerisinde de yazabiliriz. Basit örnekler gösterdiğim için, main methodunun içerisinde tanımlayacağım. Farklı bir dosya açarak, class tanımlamasını orada da yapabiliriz. Main methodunun bulunduğu dosyamızda class oluştururken, class başına public anahtar kelimesi getiremeyiz.

class Cat {

    //oluşturduğumuz class

}

public class FirstClass {

    public static void main(String[] args){ 

        //ana method

    }

}

  Cat adında basit bir class oluşturduk. İçerisine name, color, age özelliklerimizi (değişkenleri) ekleyelim.

  JAVA geliştiricileri class yapılarını ayırt edebilmek için class isimlendirmelerinde *CamelCase yöntemini kullanıyorlar. Tabi bu zorunlu bir durum değildir. Siz istediğiniz yöntemi kullanabilirsiniz.

class Cat {

    int age;

    String name;

    String color;

}

public class FirstClass {

    public static void main(String[] args){

        //ana method

    }

}

  Class yapısının özelliklerini tanımladıktan sonra, artık main methodumuz içerisinde yaşayan (yer kaplayan) bir nesne haline çevirebiliriz.

class Cat {

    int age;

    String name;

    String color;

}

public class FirstClass {

    public static void main(String[] args){

        Cat cat1 = new Cat(); 

    }

}

  Main methodumuz içerisinde oluşturduğumuz yapı biraz tanıdık geliyor değil mi? Evet, aynı yeni bir String değişken tanımlar gibi nesne tanımlayabiliyoruz. Cat objesini tanımladığımız için, yaşayabilen bir obje olarak tanımlayabildik. Ama biz String karakteri tanımlamadık ki, onda neden hata vermedi? String değişken tipi aslında JAVA IDE’mizde bulunan paketlerde tanımlı olarak geliyor.

  Nesnemizi yaşayan bir varlık olarak tanımladığımıza göre, içerisine nasıl özellik değerlerini ekleyebileceğimizi inceleyelim.

class Cat {

    int age;

    String name;

    String color;

}

public class FirstClass {

    public static void main(String[] args){

        Cat cat1 = new Cat(); 

        cat1.color = "yellow";

        cat1.age = 2;

        cat1.name = "Tarcin";

   }

}

  Oldukça kolaymış değil mi? cat1.color = “yellow” ifadesiyle, cat1'in içinde olan color değişkenine eriş ve sağdaki değere göre değiştir söylemiş oluyoruz. Bunları yazdırmak istediğimizde de, kullanımını aynı şekilde gerçekleştirmemiz gerekir.

class Cat {

    int age;

    String name;

    String color;

}

public class FirstClass {

    public static void main(String[] args){

        Cat cat1 = new Cat();

        cat1.color = "yellow";

        cat1.age = 2;

        cat1.name = "Tarcin";

        System.out.println("Kedinin ismi: " + cat1.name + "\nKedinin yaşı: " + cat1.age + "\nKedinin rengi: " + cat1.rengi);   

    }

}

  Oluşturduğumuz kodu çalıştırıp, nasıl bir çıktı verdiğini kontrol edelim.

  Aynı örnek üzerinden, nesnemize davranış ekleyelim.

class Cat {

    

    String name;

    String color;

    int age;

    int hungry;

    

    void eatFood(int foodVal) {

        this.hungry += foodVal;

    }

        

}

public class FirstClass {

    public static void main(String[] args) {

        

        Cat cat1 = new Cat();

        

        cat1.name = "Tarcin";

        cat1.color = "yellow";

        cat1.age = 3;

        cat1.hungry = 2;

        

        System.out.println("Kedinin ismi: " + cat1.name + "\nKedinin yaşı: " + cat1.age + "\nKedinin rengi: " + cat1.color);

        System.out.println("Kedinin açlık durumu: " + cat1.hungry);

        

        cat1.eatFood(3);

        

        System.out.println("Kedinin açlık durumu: " + cat1.hungry);

    }

}

  void eatFood() , void anahtar kelimesi methodumuzun herhangi bir değer döndürmeyeceğini belirtiyor.

void eatFood(int foodVal), method içerisinde kullanabilmek için integer tipinde fooVal değişkenini parametre olarak belirtiyorum.

this.hungry += foodVal; , parametremden aldığım değeri class içerisinde hungry değeri ile topluyorum.

cat1.eatFood(3); , ana yapı içerisinde eatFood() methodunu çağırarak, 3 değerini parametre olarak gösteriyorum.

Bu method sonucunda, class yapımın içerisindeki hungry değeri 5 olarak değişiyor.

Github reposunu inceleyerek, diğer örneklere göz atınız: 

https://github.com/kahilkubilay/JAVA_OOP_Fundamentals/blob/master/class_property_method_example.java

Constructor (İnşaatçı, Yapıcı) Yapısı

  Türkçe meali inşaatçı, yapıcı anlamlarına gelmektedir. Constructor class içerisinde oluşturduğumuz özelliklerin(değişkenlerin) varsayılan değerlerini oluşturmak için kullanılan bir yapıdır. Constructor methodunu kullanarak bir/birden fazla özellik alma, duruma göre farklı işlemler uygulayabiliriz.

//kedi nesnemiz

class Cat{

    

    String name;

    String color;

    int age;

    int hungry;

    

    void eatFood(int foodVal) {

        this.hungry += foodVal;

    }

    

    //constructor methodumuz

    public Cat() {

        this.name = "değer girilmedi";

        this.color = "değer girilmedi";

        this.age = 0;

        this.hungry = 0;

    }

    

}public class constructor_example {

    public static void main(String[] args) {

        // main method

        

        //kedi nesnemiz

        Cat cat1 = new Cat();

        

        System.out.println(cat1.name + "\n"

                + cat1.color + "\n"

                + cat1.age + "\n"

                + cat1.hungry + "\n");

    }

}

  *Constructor özel tanımlı methodlardır. Bundan dolayı, bulunduğu class ile aynı ismi taşımalıdır.

  Constructor en basit haliyle yukarıdaki örnekte olduğu gibi oluşturulabilir. Constructor methodu içerisinde “this.” kullanımı gibi bir ifade mevcut. Daha önce javascript ile uğraşanlara tanıdık gelecektir. this.name: class içerisinde bulunan name değişkenini gösterir. Farklı bir atama yaptığımız gibi, nesnemiz içerisinde bulunan name değişkenini değerini etkileyecektir.

  Yapımıza parametre girişi ekleyerek, işlevselliğini biraz arttıralım.

//kedi nesnemiz

class Cat{

    

    String name;

    String color;

    int age;

    int hungry;

    

    void eatFood(int foodVal) {

        this.hungry += foodVal;

    }

    

    //constructor methodumuz

    public Cat() {

        this.name = "değer girilmedi";

        this.color = "değer girilmedi";

        this.age = 0;

        this.hungry = 0;

    }

    //farklı constructor methodumuz

    public Cat(String name, int age) {

        this.name = name;

        this.age = age;

    }

    

}

public class constructor_example {

    public static void main(String[] args) {

        // main method

        

        //kedi nesnemiz

        Cat cat1 = new Cat();

        Cat cat2 = new Cat();

        cat2.name = "Tarcin";

        cat2.age = 2; 

       

        System.out.println(cat1.name + "\n"

                + cat1.color + "\n"

                + cat1.age + "\n"

               + cat1.hungry + "\n");

        System.out.println(cat2.name + "\n"

                + cat2.color + "\n"

                + cat2.age + "\n"

                + cat2.hungry + "\n");

    }

}

  Peki Constructor yapısı oluşturmasaydık ne olacaktı? Derleyici değişkeni oluşturduğunuz satırda bir değer ataması olup/olmama durumunu kontrol edecek. Burada da bir tanımlama olmasaydı, değişken tipine göre default değer ataması yapacaktı.

  JAVA programlama dilinde değişkenlerin varsayılan değerleri:

String = null;

float = 0.0;

double = 0.0;

int = 0;

  Constructor ve atama işlemleri olmadan, class değişkenlerinin nasıl bir sonuç verdiğini kontrol edelim:

//özelliklerin(değişkenlerin) default değerleri

class cat{

    String name;

    String color;

    int age;

    int hungry;

    

     void eatFood(int foodVal) {

        this.hungry += foodVal;

    }

}

public static void main(String[] args) {

    Cat cat1 = new Cat();

    System.out.println(cat1.name + "\n"

                + cat1.color + "\n"

                + cat1.age + "\n"

                + cat1.hungry + "\n");

}

  Constructor bir method olduğuna göre, parametre alabileceğini söylemiştik. Aldığı parametrelere göre birden fazla Constructor tanımlaması yapabiliriz. Aynı parametre sayı ve tipine sahip şekilde ürettiğimiz constructorlar hata verecektir. Şimdi farklı bir constructor daha tanımlayıp, ürettiği sonucu inceleyelim:

//kedi nesnemiz

class Cat{

    

    String name;

    String color;

    int age;

    int hungry;

    

    void eatFood(int foodVal) {

        this.hungry += foodVal;

    }

    

    //constructor methodumuz

    public Cat() {

        this.name = "değer girilmedi";

        this.color = "değer girilmedi";

        this.age = 0;

        this.hungry = 0;

    }

    //farklı constructor methodumuz

    public Cat(String name, int age) {

        this.name = name;

        this.age = age;

    }

    //farklı constructor methodumuz  

    public Cat(String name, String color, int age, int hungry){

        this.name = name;

        this.color = color;

        this.age = age;

        this.hungry = hungry;

    }

    }

public class constructor_example {

    public static void main(String[] args) {

        // main method

        

        //kedi nesnemiz

        Cat cat1 = new Cat();

        Cat cat2 = new Cat();

        Cat cat3 = new Cat();

        cat2.name = "Tarcin";

        cat2.age = 2; 

       

        System.out.println(cat1.name + "\n"

                + cat1.color + "\n"

                + cat1.age + "\n"

               + cat1.hungry + "\n");

        System.out.println(cat2.name + "\n"

                + cat2.color + "\n"

                + cat2.age + "\n"

                + cat2.hungry + "\n");

        System.out.println(cat3.name + "\n"

                + cat3.color + "\n"

                + cat3.age + "\n"

                + cat3.hungry + "\n");

    }

}

  Birden fazla constructor tanımlaması yaptık. Bu kadar constructor içerisinde nesnemiz hangisini alması gerektiğini nasıl ayırt edebilecek? Main methodumuz içerisinde çağırdığımız yöntem, class içerisinde kendisine en çok benzeyen constructor methoduna ulaşacaktır.

Github reposunu inceleyerek, diğer örneklere göz atınız: 

https://github.com/kahilkubilay/JAVA_OOP_Fundamentals/blob/master/constructor_example.java

Nesne Yönelimli Programlamanın Dört Temel Prensibi

  Bir nesneye özellik ve davranış tanımlarken, dış dünya ile nasıl iletişim kuracağını tanımlamış oluyoruz. Nesnenin dış dünya ve diğer nesneler ile olan iletişimi soyutlama işlemidir.

  Back-end ve front-end kavramları, bunun örneğini vermek için gayet uygun bir mekanizma. Bir web sayfasını açtığımızda ekranımıza yansıyan herşey front-end alanının içerisindedir. Görseller, butonlar, yazılar… Bir butona tıkladıktan sonra, arka tarafta back-end çalışmaya başlar. Biz butonun ne yaptığını bilirken, nasıl çalıştığını bilmeyiz.

  Google üzerinde aramalar yapıyoruz ancak Google arka planda neler çalıştırıyor, bizim hangi verilerimize erişim sağlıyor, hangi verilerimizi saklıyor bunlardan bihaberiz.

  Bunlar soyutlama işlemlerinin örnekleridir. Bundan sonra göreceğimiz encapsulation(kapsülleme) işlemi aynı zamanda bir abstraction (soyutlama) işlemidir. Encapsulation ne olduğunu açıkladıktan sonra, işin kod tarafını biraz inceleyelim.

Encapsulation (Kapsülleme) Prensibi

  Kapsülleme kelime anlamını, bir varlığın yapısını dışarıyla temasından doğabilecek sonuçları önlemek amacıyla koruma altına almak olarak tanımlayabiliriz. Örnek olarak bir bebeğin embriyo dönenimde kapsülü annesinin karnıdır. Anne karnı bebeği dış etmenlerden koruyan bir kapsül görevi görür.

  Biz de özelliklerimizin iç yapısı bütünlüğünü sağlamak, dışarıdan olabilecek müdahalelere karşı koruyabilmek için kapsülleme(encapsulation) prensibini uygulayacağız.

//kedi nesnemiz

class Cat{

      

    public String name;

    public String color;

    private int age;

    int hungry;

}

public class constructor_example {

    public static void main(String[] args) {

        // main method

    }

}

  İlk Cat class içerisinde oluşturduğumuz özellikleri inceleyelim. Public, private gibi kavramlar eklemişiz. Bunlar özelliklerimize nasıl erişebileceğimizi belirten, erişim belirleyicileridir. Bundan sonra biz özelliklerimize cat1.age ifadesi ile ulaşamayacağız. Çünkü artık erişimi bir kapsül içerisine aldık, korumaya başladık. Öncellikle erişim belirleyicilerimizin özelliklerini bakalım:

Public: Herkesin erişimene açık olan değişkenlerdir.

Private: Bulunduğu class içerisinde erişim sağlanabilen değişkenlerdir.

Protected: Bulunduğu paket veya miras alma yöntemi ile (extends) erişim sağlanabilen değişkenlerdir.

Default: Aynı pakettekilerin erişim sağlayabildiği değişkenlerdir. Kodları dikkatli incelediyseniz, şuana kadar bu erişim belirleyicisini kullandığımızı farketmişsinizdir.

//kedi nesnemiz

class Cat{

      

    public String name;

    public String color;

    private int age;

    int hungry;

}

public class constructor_example {

    public static void main(String[] args) {

        // main method

        Cat cat1 = new Cat("Tarcin", "yellow", 2, 3);

        

        System.out.println(cat1.name);

        System.out.println(cat1.age);

}

  cat1 adında yeni bir nesne oluşturduk. Public olarak tanımlanan cat1.name değişkenine ulaşmak istediğimde, hiçbir problemle karşılaşmıyorum. Ancak Private olarak tanımlanan cat1.age değişkenime erişmek istediğimde bir hata ile karşılaşıyoruz.

  Peki cat1.age nesnemize erişmek için nasıl bir yok izlemeliyiz? Bunun için setter ve getter methodlarını kullanmamız gerekiyor.

Setter ve Getter Methodları

Setter: Method parametre değerini ayarlar. Değişken değerimize farklı veya yeni bir değer girmek istediğimiz yerlerde setter methodunu kullanacağız.

Getter: Setter methodundan girilen değeri döndürür. Değişken değerimize ulaşmak istediğimiz yerlerde getter methodunu kullanacağız.

//kedi nesnemiz

class Cat{

      

    public String name;

    public String color;

    private int age;

    int hungry;

    //main constructor

    public Cat() {

        this.name = "isim degeri girilmedi.";

        this.color = "renk degeri girilmedi.";

        this.age = 0;

        this.hungry = 0;

    }

    

    //parameters constructor

    public Cat(String name, String color, int age, int hungry) {

        this.name = name;

        this.color = color;

        this.age = age;

        this.hungry = hungry;

    }

   

    //getter age

    public int getAge(){

        return age; 

    }

    //setter age

    public void setAge(int age){

        this.age = age;

    }

}

public class constructor_example {

    public static void main(String[] args) {

        // main method

        Cat cat1 = new Cat();

       

        cat1.setAge(2);   

        System.out.println(cat1.getAge());     

    }

}

  Getter ve setter methodlarını karıştırmamak için, getter değer döndürür, setter ise değer döndürmez olarak kodlayabilirsiniz.

Github reposunu inceleyerek, diğer örneklere göz atınız: 

https://github.com/kahilkubilay/JAVA_OOP_Fundamentals/blob/master/encapsulation_example.java

Inheritance (Kalıtım, Miras Kalma) Prensibi

  Objeler doğada bulundukları türe göre özellik ve davranış sergilerler. Bu özellik ve davranışlar bulundukları türler arasında birçok benzerlik içerir. Kedi türü dört ayaklıdır. Bu özellik sonradan oluşacak bütün kediler için benzer bir özelliktir. Bir Van Kedisi, kedi türünün bütün özelliklerini korur. Kedi türünden farklı olarak onu özel yapan bazı yeni özellikler kazanır. Van Kedisinin yeni kazandığı özellikler, onu kedi türü olmaktan çıkarmaz. Van Kedisi kedi türüne aitken, kedi türünün geneli Van Kedisinin özelliklerini sergilemez.

  Farklı bir örnek üzerinden senaryomuzu tekrar inceleyelim. Araba class yapısı içerisindeki özellikleri bakalım. Arabanın dört kapısı, dört tekerleği, bir direksiyonu, bir motoru var. Davranışlarına baktığımızda kontağı çevirdiğimiz gibi çalışır, gaza bastığımızda ilerler, frene bastığımızda durma işlemini gerçekleştirir. Araba türünün geneline baktığımızda bu özellik ve davranışlar geçerlidir. Kategorilere ayırmak için elimizde üç farklı araba türü olduğunu varsayalım. Bu arabaların markalarına göre yeni class yapıları oluşturacağız. Bu markalardan biri olan Mercedes, miras yöntemiyle araba classs yapısının aynı özellik ve davranışlarına sahip olacaktır. Mercedes markası için tekrardan tekerlek sayısı, direksiyon sayısı, gaz methodu, fren methodu gibi özellik ve davranışları tanımlayacak mıyız? Hayır. Mercedes class yapısı, araba class yapısının bir alt class olduğu için, bütün özellikleri kalıtım yoluyla Mercedes class yapısına aktaracağız.

  Yukarıdaki şemayı inceleyerek, benzer örnekleri aşağıdaki gist içerisine ekleyiniz: 

https://gist.github.com/kahilkubilay/d36cf1368476fd9dfdd493091273ddbc

Inheritance (Kalıtım, Miras Kalma) Yapısı

  Bir class yapısının özellik ve davranışlarını, farklı bir class içerisine aktarma işlemine inheritance(kalıtım, miras kalma) denir. Özellik ve davranışlarını aktardığımız class üst class(ata class, temel class), aktarıldığı class alt class(türetilmiş class, genişletilmiş class) olarak adlandırılır.

class Cat{

    

    public String name;

    public String color;

    public int age;

    public int hungry;

    

    void eatFood(int foodVal) {

        this.hungry += foodVal;

    }

    

}

class VanCat extends Cat{

    //Kalıtım yoluyla VanCat nesnemizi oluşturduk

}

class BlueRussiaCat extends Cat{

    //Kalıtım yoluyla BlueRussiaCat nesnemizi oluşturduk

}

class PersianCat extends Cat{

    //Kalıtım yoluyla PersianCat nesnemizi oluşturduk

}

public class inhertitance_ex {

    public static void main(String[] args) {

        // main method

        

    }

}

  class VanCat extends Cat{} : Inheritance yöntemini, extends anahtar kelimesini kullanarak uygulayabiliyoruz. İlk tanımlanan yeni oluşturacağımız class ismi, ardından tanımlayacağımız da miras alınacak olan class ismi şeklinde oluşturuyoruz.

  Inheritance yöntemi ile oluşturduğumuz sınıflar üzerinde işlemler yapabiliriz. VanCat, BlueRussiaCat, PersianCat class yapıları altında tanımlayacağımız özellikler, Cat class yapısını etkilemeyecektir.

public static void main(String[] args) {

        // main method

        

        VanCat cat1 = new VanCat();

        BlueRussiaCat cat2 = new BlueRussiaCat();

        PersianCat cat3 = new PersianCat();

        

        cat1.name = "Tarçın";

        cat2.color = "blue";

        cat3.age = 3;

        

        System.out.println(cat1.name);

        System.out.println(cat2.color);

        System.out.println(cat3.age);

    }

Github reposunu inceleyerek, diğer örneklere göz atınız: 

https://github.com/kahilkubilay/JAVA_OOP_Fundamentals/commit/9b59250069b12f992f75f4b29ffad0b7eb63beb2

Polymorphism(Çok Biçimlilik, Çok Şekillilik) Prensibi

  Inheritance(miras alma, kalıtım) yoluyla türetilen class yapıları, üst class yapısının davranış ve özelliklerini alır. Bu özellik ve davranışlar yeni oluşturulan class yapısına ait olduğu için, farklı şekillerde tanımlamalarını gerçekleştirebiliriz.

  En son incelediğimiz araba örneğimizden devam edelim. Araba class yapısından, üç farklı class türetmiştik. Mercedes üzerinde ekstra bir özellik olarak otomatik sürücü olduğunu düşünelim. Tanımlayacağım bu otomatik sürücü özelliği, Araba class yapısı içerisinde bulunmuyor. Sadece Mercedes markalı araçlara özgü bir davranış.

Override ve Overloading Methodları

Override: Kalıtım yoluyla oluşturulan class üzerinde, yeni bir method belirleme işlemine override(üzerine yazma) methodu adı verilir.

Overloading: Kalıtım yoluyla oluşturulan class üzerinde, var olan bir methodu farklı durumlara özgü olarak yeniden tanımlama işlemine overloading(yeniden yazma) methodu adı verilir.

Bir Cat class yapısı oluşturarak, aşağıdaki özellik ve metodları içerisinde tanımlıyorum.

class Cat{

    

    private String name;

    private int age;

    

    

    //default constructor

    public Cat() {

        this.name = "İsim değeri girilmedi";

        this.age = 0;

    }

    

    //params constructor

    public Cat(String name, int age) {

        this.name = name;

        this.age = age;

    }

    

    //getter

    public String getName() {

        return this.name;

    }

    public int getAge() {

        return this.age;

    }

    //setter

    public void setName(String name) {

        this.name = name;

    }

    public void setAge(int age) {

        this.age = age;

    }

    

    public void ioCat(){

        System.out.println("Kedimizin adı: " + this.getName()

                + "\nKedimizin yaşı: " + this.getAge() + "\n");

    }

    

}

  Şimdi Cat class yapımızı kullanarak, VanCat adında yeni bir class türetelim. Van kedisini özelliği olan, göz renklerini tanımlayalım. Cat class yapısında tanımlanmayan bir özellik olacak. Yazdırma methodumuzu buna göre düzenleyelim.

class VanCat extends Cat{

    private boolean eyeColor;

    

    //params constructor 

    public VanCat(String name, int age, boolean eyeColor) {

        super(name, age);

        this.eyeColor = eyeColor;

    }

    

    //get eyeColor

    public boolean getEyeColor() {

        return this.eyeColor;

    }

    

    //set eyeColor

    public void setEyeColor(boolean eyeColor) {

        this.eyeColor = eyeColor;

    }

    

    public void ioCat() {

        if(this.eyeColor == true) {

            System.out.println("Kedimizin adı: " + this.getName()

            + "\nKedimizin yaşı: " + this.getAge()

            + "\nKedimiz göz renkleri farklıdır." + "\n");

        }else {

            System.out.println("Kedimizin adı: " + this.getName()

            + "\nKedimizin yaşı: " + this.getAge()

            + "\nKedimiz göz renkleri farklı değildir." 

            + "\nNesne yanlış yerde tanımlanmıştır, lütfen ait olduğu sınıfı düzeltiniz." + "\n");

        }

    }

    

}

  VanCat class yapısından oluşturacağımız her nesne, default değeri true olan eyeColor özelliği ile birlikte oluşacaktır. Tanımlanan kedinin gözleri renkli değilse bir uyarı mesajı vererek nesnemizi farklı bir class altında tanımlamamızı isteyecektir. Ana methodumuz içerisinde nesnelerimizi oluşturarak, döndürdüğü sonucu kontrol edelim.

public class polymorphism_example {

    public static void main(String[] args) {

        // main method

        

        Cat cat1, cat2, cat3;

        

        cat1 = new Cat("Tarçın", 2);

        cat2 = new VanCat("Mesir", 3, true);

        cat3 = new VanCat("Macun", 4, false);

        

        cat1.ioCat();

        cat2.ioCat();

        cat3.ioCat();

    }

}

  Polymorphism ile birlikte, JAVA OOP temellerinin sonuna geldik. Yazıyı sonlandırmadan önce, şunları söylemek isterim. JAVA konusunda henüz yeteri kadar donanımlı değilim ancak ilerde JAVA dilinde kendimi geliştirmek istiyorum. Bu yazı, Eskişehir Osmangazi Üniversitesi, BÖTE Bölümü, Nesne Yönelimli Programlama dersi için hazırlanan bir dökümandır. Yanlış veya eksik olduğunu düşündüğünüz bir noktayı yorumlar kısmında dile getirebilirsiniz. Umarım bu kaynağı inceleyen insanlara az da olsa faydası dokunabilmiştir.

Elimden geldiğince bu yazıyı güncelleyeceğim. Özel bir yorum iletmek için, [email protected] üzerinden iletişime geçebilirsiniz. Diğer bir yazıda, JAVA üzerinde veritabanı işlemlerinden devam edeceğim. O zamana dek, kendinize dikkat edin.

---

*CamelCase: Program içerisinde kullanılan tanımlamaların ilk harfinin büyükle başladıktan sonra, her kelime başlangıcının büyük harfle devam etmesidir. ÖR: YeniDeger, ToplamSonuc, BolumdenKalan, AhmetinYasi

Kaynakça:

Sadi Evren Şeker — https://www.youtube.com/watch?v=H_SKv07-648&list=PLh9ECzBB8tJPFTpuHKhYayis0H9pS6_rI&index=1

Oracle Docs — https://docs.oracle.com/javase/tutorial/

Bunlar İlginizi Çekebilir