NESNE YÖNELİMLİ PROGRAMLAMA – HAFTA # 4 Yrd.Doç.Dr.Hacer Karacan İçerik ▫ Nesne Oluşturma ▫ Nesnenin Yaşam Süreci ▫ Dahili Sınıflar Nesne Oluşturma • Java dahil pek çok programlama dilinde oluşturmak için new anahtar kelimesi kullanılır. nesne • new anahtar kelimesi belirtilen sınıftan yeni bir nesne oluşturur ve bir referans değeri tanımlar. ▫ Örneğin Kitap sınıfından bir nesne oluşturmak istersek; Kitap kitapA = new Kitap(); ifadesini kullanırız. Kitap kitapA = new Kitap(); • Sol tarafta Kitap sınıfının adı ve nesnenin değişken adı bulunmaktadır. • Bu kısım sağ taraftan gelen referans bilgisini tutmak için yazılır. • Baştaki sınıf ismi tutulan referansın ne tür bir nesne olduğunu tanımlar. • Bu işlem sonucu oluşturulan nesneye kitapA isimli değişken vasıtasıyla erişim sağlanmaktadır. • Eşittir operatörünün sağ tarafına bakarsak new anahtar kelimesi ve Kitap sınıfıyla aynı isimdeki Kitap() metodunu görürüz. • Bu yapı Kitap sınıfından bir nesne oluşturur. Bu nesne için bellekte bir alan tahsis eder ve bellekteki bu alanın referans bilgisini eşittirin sol tarafına gönderir. new Operatörü • Bellekte yeni nesne için yer ayırır. • Sınıf içerisinde bulunan ve yapılandırıcı olarak adlandırılan metodu çağırır. • Yeni nesnenin referans değerini döndürür. Bu değer bir referans değişkeninde saklanır. • Yeni bir nesne oluşturmak için bir önceki örneğimizde Kitap kitapA = new Kitap(); İfadesini kullanmıştık. Bu ifade istenirse sol parça önce tanımlanmak şartıyla iki satırda tanımlanabilir. Kitap kitapA; // nesne referans değişkeni tanımlama kitapA = new Kitap(); // yeni bir kitap nesnesi oluşturup referans değerini kitapA değişkenine aktarma. Nesneler ve Gösterimleri Değer ile çağırma Değişkenin aldığı değer metoda gönderilir. Metot içinde yapılan işlemler orjinal nesneyi değiştirmez. Referans ile çağırma Metoda değişkenin (nesnenin) kendisi göderilmiş gibi olur ve nesnenin bellekteki adresi yollanır. Metot içinde yapılan işlemler orjinal nesneyi değiştirir. Değer ile çağırma int i, j; i = 10; j = i; i = 20; System.out.println(i + “ ve “ + j); 20 ve 10. Çıktı: 20 ve 10 Referans ile çağırma İki basit veri tipi kullanıldığında değişkenler birbirinden bağımsız hareket ederler ve iki ayrı değişken olarak değer alabilirler. Nesne kullanıldığında atama işlemi esnasında “=” işaretinin sağındaki nesnenin referansı (adresi) işaretin solundaki referansa (adrese) eşitlenir. Dolayısıyla bir değişken ismi kullanarak yapılan bir değişim diğer değişkeni de (ismi farklı olsa da) aynı şekilde değiştirmektedir. Bunun sebebi iki nesnenin de referanslarının (adreslerinin) aynı olmasıdır. Nesne Değişkenleri • Java ve diğer nesneye yönelimli programlama dillerinde genel olarak iki tür değişken vardır. ▫ nesne değişkenleri ▫ ilkel değişkenler Nesne Değişkenleri • Nesne Değişkenleri nesnelerin bellekteki referans değerlerini tutan değişkenlerdir. • Bu değişkenler de tanımlandıkları anda bellekten yer ayırırlar ancak ayrılan bu alan oluşturulacak olan nesnenin referans bilgisini tutmak içindir. • Nesne değişkenleri tanımlandığı anda new ile bir nesne oluşturulursa o nesnenin referans değeri değişkene atanır. Ancak nesne oluşturulmaz ise o zaman değişkene null yani boş değeri atanır. null Referansı • Programcılıkta null ifadesi, bellekte ayrılan bir alanı göstermekle görevli değişkenlerin hiçbir yeri göstermediği durumları temsil eder. • Nesne değişkenlerinin görevlerinin, nesnenin bellekteki konumunu gösterdiğine göre, nesne değişkenleri de null değerini alabilirler. • Nesne değişkenleri tanımlanırken eğer new ile nesne oluşturulmaz ise nesne değişkeninin değeri null olur. Kitap kitapD; // kitapD null değerini alır Kitap kitapD=null //başlangıç ifadesi olarak null alabilir. null Referansı • Bir nesneye olan ihtiyacımız bittiğinde ondan kurtulmak istersek null ifedesine başvururuz. • Java’da eğer bir nesnenin referans değeri bir nesne değişkeninde tutulmuyorsa bu nesne bellekten silinir. Kitap kitapC= new Kitap(); // Kitap sınıfından bir nesne oluşturulur ve referansı kitapC ye atanır. kitapC=null; // kitapC ye null değeri atandığından bir önceki satırda satırda oluşturulan nesneye erişilemez ve sistemden silinir. Referans Atama Yöntemleri 1. Bir nesne değişkeni oluşturduğumuzda new ile yeni bir nesne oluşturursak oluşturulan nesnenin referansı o nesne değişkenine atanır. 2. Nesne değişkeni oluşturulduğunda nesne oluşturulmazsa null referans değeri atanır. 3. Başka bir durum ise nesne değişkeni oluşturulduğunda var olan bir nesnenin referansının atanmasıdır. Referans Atama • Kitap kitapC= kitapA; • Bu durumda iki nesne değişkeni de aynı referans değerine sahip olacaktır. • Bunun anlamı her iki nesne değişkeni de aynı nesneyi temsil ediyor demektir. Nesnenin kopyalanması anlamına gelmez. • Nesne değişkenleri programın icrası sırasında farklı referans değerler alabilir. • Bir nesneye erişebilmek için en az bir nesne değişkeninin o nesneyi göstermesi gerekmektedir. Değişken Tanımlama • Bir sınıf oluşturulurken o sınıftan türeyecek nesnelerin özellikleri değişkenlerle tanımlanır. • Bu değişkenler ilkel değişkenler olabileceği gibi nesne değişkenleri de olabilmektedir. pubilc Class Kitap{ public String kitapAdı; public String yayınEvi; public Date basımTarihi; public int sayfaSayısı; public String kitabınAdınıGöster(){ return kitapAdı; } • Değişkenler nesne özelliklerini temsil etmenin dışında metodların içerisinde işlemler için de tanımlanabilirler. ▫ Bu değişkenler yerel değişkenler olarak adlandırılırlar ve metod içerisinde tanımlanmaları şarttır. Metod Çağırma • Bir nesnenin metodunu çağırmak için nokta operatörünü kullanırız. Nesnenin referansını tutan değişken isminin sağına nokta koyduktan sonra metodun ismini ve varsa parametre değerlerini çağırarak metodu çağırmış oluruz. pubilc Class Kitap{ public String kitapAdı; public String yayınEvi; public Date basımTarihi; Kitap kitap1 = new Kitap( ); public int sayfaSayısı; kitap1.maliyet= 10.00; public float maliyet; float fiyat= kitap1.satisFiyatiHesapla(); public float satisFiyatiHesapla( ){ if (fiyat<20) float fiyat=0.0; fiyat=maliyet+maliyet*0.18 return fiyat; } } …… // maliyete %18 kdv eklenir Başka metotları çağıran metotlar Java dilinde bir metodun gövdesinde başka metot çağırılabilir. main() metodunun içinde başka nesnelere ait metotlar nesne adıyla birlikte çağırılmaktadır. Bir metot ait olduğu sınıfın içinde başka bir metodu doğrudan adıyla çağırabilir. (this işaretçisi de kullanılabilir.) Başka metotları çağıran metotlar Aşağıdaki örnekte oyunSorusu() metodunun içinden oyunOyna() metodu doğrudan adıyla çağırılmıştır. public void oyunSorusu(){ String cevap; Scanner klavye = new Scanner(System.in); do { oyunOyna(); System.out.print(“Bir kere daha ”); System.out.println(“oynamak istiyor musun ? ”); cevap = klavye.next(); } while (cevap.equalsIgnoreCase(“Evet”)); System.out.println(“iyi gunler”); } Başka metotları çağıran metotlar – örnek /** * SayiOyunu sinifi bilgisayarin rasgele sectigi bir sayiyi * bulmak icin kullanilir. */ import java.util.*; public class SayiOyunu { int bulunacakSayi; int girilenSayi; boolean sayiBulundu; private void buyukKucukGoster() { if (girilenSayi > bulunacakSayi) { System.out.print("Sayiniz buyuk. "); System.out.println("Daha kucuk bir sayi girin."); } Başka metotları çağıran metotlar – örnek else if (girilenSayi < bulunacakSayi) { System.out.print("Sayiniz kucuk. "); System.out.println("Daha buyuk bir sayi girin."); } else { // Sayi bulundu. System.out.println("Sayiyi buldunuz, tebrikler."); sayiBulundu = true; } } Başka metotları çağıran metotlar – örnek public void oyunSorusu() { String cevap; Scanner klavye = new Scanner(System.in); do { oyunOyna(); System.out.print("Bir kere daha oynamak "); System.out.println("istiyor musun ? (Evet-Hayir)"); cevap = klavye.next(); } while (cevap.equalsIgnoreCase ("Evet")); System.out.println("iyi gunler"); } private void oyunaBasla() { bulunacakSayi = (int) (Math.random() * 100 + 1); sayiBulundu = false; } Başka metotları çağıran metotlar – örnek private void sayiSor() { Scanner klavye = new Scanner(System.in); do { System.out.print("1 ile 100 arasinda "); System.out.println("bir sayi girin."); girilenSayi = klavye.nextInt( ); } while ((girilenSayi < 1) && (girilenSayi > 100)); } private void oyunOyna() { oyunaBasla(); do { sayiSor(); buyukKucukGoster(); } while (!(sayiBulundu)); } } Başka metotları çağıran metotlar – örnek public class DeneSayiOyunu { public static void main(String [] args) { SayiOyunu oyun1 = new SayiOyunu(); oyun1.oyunSorusu(); } } Yukarıdaki örnekte SayiOyunu sınıfı içindeki metotlar birbirlerini çağırabilmektedir. Bir metot kendi sınıfının dışından çağırılmak istendiğinde nesneyle birlikte kullanılması gerekir. DeneSayiOyunu sınıfı SayiOyunu sınıfına ait oyunSorusu() metodunu çağırırken oyun1 adlı nesneyle çağırmaktadır. Başka metotları çağıran metotlar – örnek Çıktı: 1 ile 100 arasında bir sayı girin. 175 1 ile 100 arasında bir sayı girin. 87 Sayiniz buyuk. Daha kucuk bir sayi girin. 34 Sayiniz kucuk. Daha buyuk bir sayi girin. 67 Sayiniz buyuk. Daha kucuk bir sayi girin. 63 Sayiyi buldunuz. tebrikler. Bir kere daha oynamak istiyor musun ? (Evet-Hayir) Evet 1 ile 100 arasında bir sayı girin. 77 Sayiniz kucuk. Daha buyuk bir sayi girin. 90 Sayiniz buyuk. Daha kucuk bir sayi girin. 85 Sayiyi buldunuz. tebrikler. Bir kere daha oynamak istiyor musun ? (Evet-Hayir) Hayir iyi gunler Metod Çeşitleme (Overloading) • Java’da aynı sınıf içerisindeki metodları birbirinden ayırmak için metod isimlerinin yanında metodun parametre sayıları ve tipleri de kullanılır. • Böylece bir sınıfın içerisinde aynı isimde birden fazla metod yazılabilir. ▫ Bu yönteme Metod Çeşitleme (Overloading) denilir. Yapılandırıcılar • Nesnelerin oluşturulması anında nesnenin bazı özelliklerini belirlemek gerektiğinde sınıfla aynı ismi taşıyan ve yapılandırıcı (constructor) olarak adlandırılan özel metodlar kullanılır. • Yapılandırıcılar new operatörüyle birlikte kullanılan özel metodlardır. Kitap roman= new Kitap( ); // Kitap() ifadesi yapılandırıcıdır • Parametresi olmayan yapılandırıcılara varsayılan yapılandırıcı denir. ▫ Varsayılan yapılandırıcı programcı tarafından tanımlanmaz ise java kendiliğinden sınıfa varsayılan yapılandırıcı atayacaktır. ▫ Ancak programcı bir yapılandırıcı metod tanımlarsa java bu desteğini çekecektir. Yapılandırıcılar • Yapılandırıcılar sınıf ismiyle aynı isimde olmak zorundadır. • Yapılandırıcılar değer döndürmezler. Bu nedenle return operatörü sadece sondandırma amaçlı kullanılır. • Aynı sınıf içerisinde birden fazla yapılandırıcı olabilir. Yapılandırıcı Çeşitleme • Metod çeşitleme yöntemi yapılandırıcılar için de geçerlidir. • Bu sayede bir sınıftan oluşturacağımız nesneler farklı oluşturma süreçlerinden geçebilir. • Metod çeşitlemede bahsedilen kurallar yapılandırıcı metodlarda da aynen geçerlidir. Yapılandırıcı Çeşitleme - Örnek class Kutu { public double x; public double y; public double z; public boolean kirilir; public int taban_kodu; // tabana gelen yüzeyin kodu 1-6 kodlar 6 yüzeyi temsil eder // 0 farketmez demek public Kutu() { x=y=z=5.0; kirilir = false; taban_kodu = 0; } public Kutu(double xe, double ye, double ze, boolean kr, int tk) { x=xe ; y=ye; z=ze; kirilir=kr; taban_kodu=tk; } } Yapılandırıcı Çeşitleme – Örnek class Depo { public static void main (String args[ ]) { Kutu k1 = new Kutu(); Kutu k2 = new Kutu(12.0, 20.0, 7.0, true, 0); System.out.println (“k1 hacmi: “ + (k1.x*k1.y*k1.z)); System.out.println (“k2 hacmi: “ + (k2.x*k2.y*k2.z)); } } Ekran Çıktısı: k1 hacmi: 125.0 k2 hacmi: 1680.0 Yapılandırıcı Çeşitleme – Örnek2 //Fazladan yüklenen Nesne kuruculari public class Araba { private String renk; private int beygirGucu; private int hiz; public Araba(String renk, int guc, int hiz) { this.renk = renk; this.beygirGucu = guc; this.hiz = hiz; } public Araba(String renk) { this.renk = renk; } public void veriGoster() { System.out.println("Renk = "+ this.renk); System.out.println("Beygir Gucu = " + this.beygirGucu); System.out.println("Hiz = " + this.hiz); System.out.println(); } public static void main(String [] args) { Araba ferrari = new Araba("kirmizi",450,320); Araba fiat = new Araba("beyaz"); fiat.setBeygirGucu(70); Çıktı: fiat.setHiz(155); Ferrari Ozellikleri System.out.println("Ferrari Ozellikleri "); Renk = kirmizi ferrari.veriGoster(); Beygir gucu = 450 Hiz = 320 System.out.println("Fiat Ozellikleri "); fiat.veriGoster(); Fiat Ozellikleri Renk = beyaz } } Beygir gucu = 70 Hiz = 155 Final Deyimi • Nesne yönelimli programlamanın getirdiği yeni kavramlarla birlikte metodlar ve sınıflar içinde değişmeyen yapılar tanımlama ihtiyacı doğmuştur. • Java’da değişkenlerin, metodların ve sınıfların özelliklerinin değişikliğe uğramasını engellemek için bu yapılara final niteliği atanır. ▫ Final değişkenler ▫ Final sınıflar ▫ Final metodlar Final değişkenler • Bir değişken final niteliği ile tanımlanırsa, ilk değeri atandıktan sonra bir daha değeri değiştirilemez. • Final değişkenlere gerekmektedir. ilk tanımlandığı anda değerinin • Örn. final float pi=3.14; final static tbmm=“Turkiye Buyuk Millet Meclisi”; atanması Final sınıflar • Nesneye yönelimli programlamanın en önemli özelliklerinden birisi bir sınıfın niteliklerini yeni bir sınıfa aktarabilmektir. • Bu yönteme kalıtım denilmektedir. • Ancak, bir sınıf final deyimiyle oluşturulduğunda bu sınıftan yeni sınıflar türetilmesi engellenmiş olur. Final metodlar • Kalıtım yöntemiyle bir sınıfın özellikleri ve işlevleri yeni sınıflara aktarılabildiği gibi yeni sınıf ta metodların üzerinde değişiklik yapabilmektedir. • Eğer bir metodun, türeyen sınıflarda değiştirilmesi istenmiyorsa final deyimi kullanılarak bu engellenebilir. Bellek temizleme • Java’da bellek yönetimi otomatiktir. • Eğer bir nesne hiçbir nesne değişkeni tarafından gösterilmiyorsa bu nesneye erişim mümkün değildir. • Erişilemiyor olması, nesnenin bellekte yer kaplamasını engellemez. • Çöp toplayıcısı bu şekilde erişilemeyen / sahipsiz nesneleri tespit ederek bellekten siler. • Programcı çöp toplayıcısının çalışmasına müdahale edemez. Ancak çağırabilir. Bunun için; System.gc(); komutu kullanılır. finalize() metodu • Bazı programlama dillerinde nesneyi düzenekleri (destructor) mevcuttur. sonlandırmak için imha • Bu yapılar genellikle belleğin temizlenmesi, diğer nesnelerle ilişkilerin sonlandırılması, açık dosyaların kapatılması gibi işlemleri içermektedir. • Java nesneyi yok etmek için çöp toplayıcı mekanizması kullandığı için ayrıca bir imha düzeneğine ihtiyaç yoktur. Ancak, yine de programcının nesne sistemden silinirken yapılmasını istediği işlemler olursa bunları yazabilmesi için finalize() metodu kullanılmaktadır. Dahili Sınıflar • Sınıf içerisinde tanımlanmış sınıflardır. • Birbiriyle bağlantılı olan yapıları bir bütün halinde tanımlamamıza yardımcı olurlar. • Okunabilirlik ve yazılabilirlik kurallarına aykırı olduklarından pek tercih edilmemektedirler. • Dahili sınıfları 3 grupta inceleyebiliriz: ▫ Üye dahili sınıflar (member classes) ▫ Yerel sınıflar (local classes) ▫ İsimsiz sınıflar (anonymous classes) Üye Dahili Sınıflar • Nesneler farklı nesnelerin biraraya gelmesiyle oluşabilmektedir. (Örn. araba) • Biraraya gelerek bir bütün oluşturan bu nesnelerin hepsini dahili sınıflar olarak ana sınıf içerisinde tanımlayabiliriz. class CevreliyiciSinif { class DahiliSinif { //.... } //... } Örnek public class Hesaplama { public class Toplama { //Dahili uye sinif public int toplamaYap(int a, int b) { return a+b ; } } public static void main(String args[]) { Hesaplama.Toplama ht = new Hesaplama().new Toplama() ; int sonuc = ht.toplamaYap(3,5); System.out.println("Sonuc = " + sonuc ); } } _________________________________________________________ Toplama sınıfına ait bir nesne oluşturmak için, önce Hesaplama sınıfına ait bir nesne oluşturmamız gerekir. Hesaplama.Toplama ht = new Hesaplama().new Toplama() ; Yerel Dahili Sınıflar • Yerel sınıflar, yalnızca içinde tanımlandıkları metodun veya bloğun içerisinde geçerlidir. • Dahili üye sınıfların çevreleyici sınıfları yerine, yerel sınıfların çevreleyici metodları veya blokları vardır. • Yerel sınıflar tanımlandıkları bu metodların veya blokların dışarısından erişilemezler. public class Sinif { public void metod() { public class YerelSinif { //... } } } İsimsiz Dahili Sınıflar • İsimsiz ifade edilebilen sınıflardır. • Özellikle olay dinleyicilerin (event listeners) devreye sokulduğu uygulamalarda sıkça kullanılırlar. • Diğer dâhili sınıf çeşitlerinde olduğu gibi, isimsiz sınıflar direk extends ve implements anahtar kelimelerini kullanarak, diğer sınıflardan türetilemez ve arayüzlere erişemez. • İsimsiz sınıfların herhangi bir ismi olmadığı için, yapılandırıcısı da (constructor) olamaz. Örnek İsimsiz Dahili Sınıf return new Toplayici() { public int hesaplamaYap() { return a + b ; } }; // noktali virgul sart Yerel Dahili Sınıf public Toplayici.topla(final int a, final int b) { public class BenimToplayicim implements Toplayici { public int hesaplamaYap() { return a + b ; } } // metod sonu return new BenimToplayicim(); } Yerel sınıflarda return new BenimToplayicim() yerine, isimsiz sınıflarda hangi sınıf tipinde değer döndürüleceği en başta return new Toplayici() ile belirtildi.