Nesne Yönelimli Programlama: Temeller
Şimdiye kadar veriyi (değişkenler, diziler) ve davranışı (metotlar) ayrı ayrı düşündük. Nesne yönelimli programlama (OOP) bunları bir araya getirir: gerçek dünyadaki bir varlığı, hem durumu (verisi) hem de davranışı (…
Nesne Yönelimli Programlama: Temeller
Şimdiye kadar veriyi (değişkenler, diziler) ve davranışı (metotlar) ayrı ayrı düşündük. Nesne yönelimli programlama (OOP) bunları bir araya getirir: gerçek dünyadaki bir varlığı, hem durumu (verisi) hem de davranışı (metotları) olan tek bir paket — yani bir nesne — olarak modelleriz. Bu bölüm, OOP'nin kalbidir; sonraki iki konu (kalıtım, soyutlama) bunun üzerine kurulacak.
Sınıf ve nesne
Sınıf (class) bir şablondur: hangi alanların ve metotların olacağını tanımlar.
Nesne (object) ise o şablondan new ile üretilen somut bir örnektir. Bir "Araba"
sınıfın varsa, garajındaki her araba o sınıftan bir nesnedir:
class Araba { String marka; // alan (durum) int hiz; void hizlan(int m) { // metot (davranış) hiz += m; } } Araba a = new Araba(); a.marka = "Toyota"; a.hizlan(40);
Her nesnenin kendi alan değerleri vardır; bir arabayı hızlandırmak diğerini etkilemez.
Örnek 1 (./Ornek1.java) iki ayrı Araba nesnesi oluşturup bağımsız durumlarını gösterir.
Kapsülleme (encapsulation)
İyi tasarlanmış bir nesne, iç verisini dışarıya açık bırakmaz. Alanları private yapar ve
erişimi kontrollü metotlarla sağlar. Buna kapsülleme denir ve amacı, nesnenin her zaman
geçerli bir durumda kalmasını garantilemektir.
Veriyi okumak için getter, yazmak için (gerekiyorsa) setter veya iş kuralı içeren metotlar yazarız:
private double bakiye; public double getBakiye() { return bakiye; } public void paraCek(double tutar) { if (tutar > bakiye) { /* engelle */ } else bakiye -= tutar; }
Bakiye private olduğundan kimse onu doğrudan hesap.bakiye = -100 yapamaz; tüm
değişiklikler kuralları uygulayan metotlardan geçer. Örnek 2 (./Ornek2.java) bir banka
hesabı üzerinde kapsüllemenin geçersiz işlemleri nasıl engellediğini gösterir.
Constructor, this ve super
Constructor, nesne new ile oluşturulurken çalışan özel bir metottur; başlangıç
değerlerini kurar. Sınıf adıyla aynı isme sahiptir ve dönüş tipi yoktur:
public BankaHesabi(String sahip, double baslangic) { this.sahip = sahip; this.bakiye = baslangic; }
this, "şu anki nesne" anlamına gelir. En çok, parametre ile alanın aynı isme sahip
olduğu durumda ayrımı netleştirmek için kullanılır (this.sahip = sahip). super ise üst
sınıfa atıfta bulunur; onu bir sonraki konu olan kalıtımda kullanacağız.
static ve final
İki anahtar kelime nesne tasarımında sık karşına çıkar:
static: Üyeyi nesneye değil, sınıfın kendisine bağlar.staticbir alan tüm nesneler arasında paylaşılan tek bir kopyadır (örneğin üretilen nesne sayısını tutan bir sayaç).staticbir metot nesne olmadan, sınıf adıyla çağrılır (Math.max(...)gibi).final: Değerin bir kez atandıktan sonra değişmeyeceğini söyler.finalbir değişken sabittir,finalbir metot ezilemez (override edilemez),finalbir sınıftan türetilemez. Sabitleri geneldepublic static finalolarak tanımlarız (KDV_ORANIgibi).
Örnek 3 (./Ornek3.java) paylaşılan bir nesne sayacı (static), bir KDV yardımcı metodu
(static) ve değişmez bir oran/ad (final) ile bu ikisini bir arada gösterir.
Özet
OOP'nin dört temel taşından ilk ikisini attık: nesneleri sınıflarla modelledik ve
kapsülleme ile durumlarını koruduk. Constructor/this ile nesneleri doğru kurmayı,
static/final ile sınıf düzeyi ve değişmez üyeleri öğrendik. Sırada, var olan kodu
yeniden kullanmamızı sağlayan kalıtım ve çok biçimlilik var.
▶ Kod Örnekleri(3)
Ornek1
çalıştırılabilir1// Ornek1: Sınıf ve nesne — alanlar ve metotlar.
2// Çalıştırma: java Ornek1.java
3public class Ornek1 {
4
5 public static void main(String[] args) {
6 // Sınıf bir "şablon"dur; nesne ise o şablondan üretilen somut bir örnektir.
7 // new anahtar kelimesi yeni bir nesne (instance) oluşturur.
8 Araba a1 = new Araba();
9 a1.marka = "Toyota";
10 a1.model = "Corolla";
11 a1.hiz = 0;
12
13 Araba a2 = new Araba();
14 a2.marka = "Honda";
15 a2.model = "Civic";
16 a2.hiz = 0;
17
18 // Her nesnenin kendi alanları (durumu) vardır; biri diğerini etkilemez.
19 a1.hizlan(40);
20 a1.hizlan(20);
21 a2.hizlan(100);
22 a1.bilgiYaz();
23 a2.bilgiYaz();
24
25 a1.frenYap(30);
26 a1.bilgiYaz();
27 }
28}
29
30// Aynı dosyada birden fazla top-level sınıf olabilir; yalnızca biri public olur.
31class Araba {
32 // Alanlar (fields) = nesnenin durumu.
33 String marka;
34 String model;
35 int hiz;
36
37 // Metotlar (methods) = nesnenin davranışı.
38 void hizlan(int miktar) {
39 hiz += miktar;
40 System.out.println(marka + " " + miktar + " km/s hızlandı.");
41 }
42
43 void frenYap(int miktar) {
44 hiz = Math.max(0, hiz - miktar);
45 System.out.println(marka + " " + miktar + " km/s yavaşladı.");
46 }
47
48 void bilgiYaz() {
49 System.out.println("-> " + marka + " " + model + " | hız: " + hiz + " km/s");
50 }
51}Ornek2
çalıştırılabilir1// Ornek2: Kapsülleme (encapsulation), getter/setter, constructor ve this.
2// Çalıştırma: java Ornek2.java
3public class Ornek2 {
4
5 public static void main(String[] args) {
6 // Constructor ile nesne oluşturulurken başlangıç değerleri verilir.
7 BankaHesabi hesap = new BankaHesabi("Selin", 100.0);
8 System.out.println(hesap.getSahip() + " hesabı açıldı. Bakiye: " + hesap.getBakiye());
9
10 hesap.paraYatir(250.0);
11 hesap.paraCek(80.0);
12 System.out.println("Güncel bakiye: " + hesap.getBakiye());
13
14 // Kapsülleme sayesinde geçersiz işlemler engellenir:
15 hesap.paraCek(10_000.0); // yetersiz bakiye
16 hesap.paraYatir(-5.0); // geçersiz tutar
17
18 // Bakiyeye doğrudan erişemeyiz (private); sadece metotlar üzerinden değişir.
19 // hesap.bakiye = 1_000_000; // <-- derlenmez: bakiye private
20 }
21}
22
23class BankaHesabi {
24 // private alanlar dışarıdan doğrudan erişilemez = kapsülleme.
25 private String sahip;
26 private double bakiye;
27
28 // Constructor: nesne kurulurken çalışır. this, "şu anki nesne" demektir;
29 // parametre ile alan aynı isimde olduğunda ayrımı sağlar.
30 public BankaHesabi(String sahip, double baslangic) {
31 this.sahip = sahip;
32 this.bakiye = Math.max(0, baslangic);
33 }
34
35 // Getter: değeri okumak için.
36 public String getSahip() {
37 return sahip;
38 }
39
40 public double getBakiye() {
41 return bakiye;
42 }
43
44 // Davranışı metotlarla kontrol ediyoruz; böylece kurallar tek yerde toplanır.
45 public void paraYatir(double tutar) {
46 if (tutar <= 0) {
47 System.out.println("Hata: yatırılan tutar pozitif olmalı.");
48 return;
49 }
50 bakiye += tutar;
51 System.out.println(tutar + " TL yatırıldı.");
52 }
53
54 public void paraCek(double tutar) {
55 if (tutar <= 0) {
56 System.out.println("Hata: çekilen tutar pozitif olmalı.");
57 return;
58 }
59 if (tutar > bakiye) {
60 System.out.println("Hata: yetersiz bakiye (istenen " + tutar + ", mevcut " + bakiye + ").");
61 return;
62 }
63 bakiye -= tutar;
64 System.out.println(tutar + " TL çekildi.");
65 }
66}Ornek3
çalıştırılabilir1// Ornek3: static ve final.
2// Çalıştırma: java Ornek3.java
3public class Ornek3 {
4
5 public static void main(String[] args) {
6 System.out.println("Başlangıç üretilen nesne sayısı: " + Urun.getUretilenAdet());
7
8 Urun u1 = new Urun("Klavye", 450.0);
9 Urun u2 = new Urun("Mouse", 250.0);
10 Urun u3 = new Urun("Monitör", 3200.0);
11
12 // static alan tüm nesneler arasında PAYLAŞILIR; nesneye değil sınıfa aittir.
13 System.out.println("Üretilen toplam ürün: " + Urun.getUretilenAdet());
14
15 // static yardımcı metot: nesne gerektirmez, sınıf üzerinden çağrılır.
16 System.out.println("KDV'li fiyat (Klavye): " + Urun.kdvEkle(u1.getFiyat()));
17
18 u1.yaz();
19 u2.yaz();
20 u3.yaz();
21 }
22}
23
24class Urun {
25 // final sabit: bir kez atanır, değişmez. Sınıf düzeyinde paylaşılan bir sabit.
26 public static final double KDV_ORANI = 0.20;
27
28 // static alan: sınıfa ait tek bir kopya, tüm nesneler paylaşır.
29 private static int uretilenAdet = 0;
30
31 // Örnek (instance) alanları: her nesneye özel.
32 private final String ad; // final: oluşturulduktan sonra değişmez
33 private double fiyat;
34
35 public Urun(String ad, double fiyat) {
36 this.ad = ad;
37 this.fiyat = fiyat;
38 uretilenAdet++; // her yeni nesnede paylaşılan sayaç artar
39 }
40
41 public static int getUretilenAdet() {
42 return uretilenAdet;
43 }
44
45 public static double kdvEkle(double tutar) {
46 return tutar * (1 + KDV_ORANI);
47 }
48
49 public double getFiyat() {
50 return fiyat;
51 }
52
53 public void yaz() {
54 System.out.printf("%-8s -> %.2f TL (KDV'li %.2f TL)%n", ad, fiyat, kdvEkle(fiyat));
55 }
56}