SEN1001 · 10. hafta · Introduction to Classes and Objects

Sınıflar ve nesneler: alanlar, metotlar, get/set

Sınıf bir kalıp, nesne o kalıptan üretilen örnek. new ile nesne oluşturma, örnek değişkenleri, nokta operatörü, private alanlar ve get/set metotları, referans değişkenler ve null. Finalin en büyük konusu burada başlıyor.

classobjectinstanceinstantiationnewinstance variable (field)instance methoddot operatorreference variablenullNullPointerExceptionaccess modifierprivatepublicencapsulationget method (accessor)set method (mutator)validation

Şimdiye kadar her şeyi main’in içine ve static metotlara yazdın. Gerçek programlar ise nesnelerden (objects) oluşur: bir banka uygulamasında hesaplar, bir oyunda oyuncular, bir okul sisteminde öğrenciler. Her nesnenin kendi verisi (alanları) ve kendi davranışı (metotları) vardır. Bu hafta ilk sınıflarını yazacaksın. Finalde bu konu yazma sorusu olarak gelir: “şu alanları ve metotları olan bir sınıf yaz, main’de iki nesne oluştur”.

Altın kurallar:

  1. Sınıf kalıp, nesne örnek. Bir Dog sınıfından istediğin kadar köpek nesnesi üretirsin.
  2. Her nesnenin kendi alanları var. Birini değiştirmek diğerini etkilemez.
  3. Değişken nesneyi değil, nesnenin referansını tutar. b = a yeni nesne yaratmaz.
  4. Alanlar private, erişim public metotlarla (get/set).
  5. Örnek metotları static değildir ve bir nesne üzerinden çağrılır.

İlk sınıf

class Dog {
    String name;     // örnek değişkenleri (instance variables / fields)
    int age;

    void bark() {    // örnek metodu (instance method): static YOK
        System.out.println(name + " (" + age + ") says Hav!");
    }
}

Sınıf bir tip tanımlar. Kendi başına hiçbir şey çalıştırmaz; içinde main yok. Onu kullanan kod başka bir sınıfın main’inde:

Dog d1 = new Dog();          // yeni nesne oluştur (instantiation)
d1.name = "Karabas";
d1.age = 3;
d1.bark();
Dog d2 = new Dog();
System.out.println(d2.name + " " + d2.age);
d2.name = "Pamuk";
d2.bark();
d1.bark();
Karabas (3) says Hav!
null 0
Pamuk (0) says Hav!
Karabas (3) says Hav!

Gözlemler:

  • new Dog() bellekte yeni bir Dog nesnesi oluşturur ve adresini döndürür. d1 bu adresi tutar.
  • Nokta operatörü (dot operator) ile nesnenin alanına ve metoduna erişilir: d1.name, d1.bark().
  • bark() içindeki name, metodu çağıran nesnenin alanıdır. d1.bark() Karabas’ı, d2.bark() Pamuk’u yazar.
  • d2’ye değer verilmeden önce alanları varsayılan değerlerde: String null, int 0. (Metot içindeki yerel değişkenlerde böyle bir varsayılan yoktur.)

Bir dosyada birden çok sınıf olabilir, ama sadece biri public olabilir ve dosya adı onun adıdır. Gerçek projelerde her sınıf kendi dosyasına konur: Dog.java, Main.java.

Kapsülleme: private alanlar, get ve set

Alanlar public olsaydı herkes acc.balance = -5000; yazabilirdi. Bunu engellemek için alanlar private yapılır ve dışarıya kontrollü public metotlar açılır. Buna kapsülleme (encapsulation) denir.

class Account {
    private String owner;
    private double balance;

    public String getOwner() { return owner; }                     // get (accessor)
    public void setOwner(String newOwner) { owner = newOwner; }    // set (mutator)
    public double getBalance() { return balance; }                 // balance için set YOK

    public void deposit(double amount) {
        if (amount > 0) balance += amount;
    }

    public void withdraw(double amount) {
        if (amount <= balance) balance -= amount;
        else System.out.println("Insufficient funds");
    }
}
Account acc = new Account();
acc.setOwner("Deniz");
acc.deposit(500);
acc.withdraw(200);
acc.withdraw(1000);
System.out.println(acc.getOwner() + " " + acc.getBalance());
acc.deposit(-50);
System.out.println(acc.getBalance());
Insufficient funds
Deniz 300.0
300.0

Bakiye sadece deposit ve withdraw ile değişebiliyor, ikisi de kural kontrol ediyor. Dışarıdan doğrudan erişmeye çalışırsan:

Acc a = new Acc();
a.balance = 1000;
Main.java:7: error: balance has private access in Acc
Erişim belirleyici (access modifier)Kim erişir?
privatesadece aynı sınıfın içi
publicher yer
(hiçbiri)aynı paketteki (package) sınıflar

get/set adlandırma

Alangetset
private String namepublic String getName()public void setName(String n)
private int agepublic int getAge()public void setAge(int a)
private boolean activepublic boolean isActive()public void setActive(boolean a)

get metodunun dönüş tipi alanın tipi, parametresi yok. set metodu void, parametresi alanın tipinde. Her alan için set yazmak zorunlu değil: bakiye gibi doğrudan değiştirilmemesi gereken alanlar için set yazılmaz.

Doğrulama (validation)

class Thermostat {
    private double celsius;

    public void setCelsius(double value) {
        if (value >= 5 && value <= 35) celsius = value;    // aralık dışı reddedilir
    }
    public double getCelsius() { return celsius; }
    public double getFahrenheit() { return celsius * 9 / 5 + 32; }
}
// main içinde:
Thermostat t = new Thermostat();
t.setCelsius(45);
System.out.println(t.getCelsius());
t.setCelsius(22.5);
System.out.println(t.getCelsius() + " " + t.getFahrenheit());
0.0
22.5 72.5

45 reddedildi, alan varsayılan 0.0’da kaldı. getFahrenheit bir alan değil, alandan hesaplanan bir değer; ayrıca saklamaya gerek yok.

Referans değişkenler

Primitive bir değişken değerin kendisini tutar. Nesne değişkeni ise nesnenin referansını (bellekteki yerini) tutar.

Account a = new Account();
a.deposit(100);
Account b = a;              // referans kopyalandı, nesne değil
b.deposit(50);
System.out.println(a.getBalance() + " " + b.getBalance());
System.out.println(a == b);
Account c = new Account();
c.deposit(150);
System.out.println(a == c);
150.0 150.0
true
false
a ──┐
    ├──► [Account: balance 150.0]
b ──┘
c ─────► [Account: balance 150.0]     başka bir nesne

== nesnelerde içeriğe değil, aynı nesne olup olmadığına bakar. a ve c’nin bakiyeleri eşit ama farklı nesneler: false. (String’lerde equals kullanmamızın sebebi de bu.)

null

Hiçbir nesneyi göstermeyen referansın değeri null’dır. null bir referans üzerinden metot çağırmak programı çökertir:

Account n = null;
n.deposit(10);
NullPointerException

Kod derlenir, çünkü derleyici sadece tipe bakar (Account’ta deposit var). Hata çalışma anında çıkar.

static ile örnek metodu farkı

main static’tir; bir nesneye ait değildir. Örnek metotları ise bir nesneye aittir. Bu yüzden main’den örnek metodu bir nesne üzerinden çağrılır:

Acc a = new Acc();
System.out.println(Acc.getBalance());     // sınıf adıyla: HATALI
Main2.java:8: error: non-static method getBalance() cannot be referenced from a static context

Doğrusu a.getBalance(). Kimin bakiyesi? a’nın. Sınıfın tek bir bakiyesi yok; her nesnenin kendisi var. Bütün nesnelerin paylaştığı static alanları 12. haftada göreceksin.

static metotörnek metodu
Nasıl çağrılırMath.sqrt(4), ClassName.m()nesne.m()
Nesne gerekir miHayırEvet
Alanlara erişimÖrnek alanlarına doğrudan erişemezKendi nesnesinin alanlarına erişir
ÖrnekisPrime(int n), maindeposit, getBalance

Çözümlü örnek: sınıf yazma sorusu

Soru: “Rectangle sınıfı yaz: private int width ve height, set metotları, getWidth(), alanı ve çevreyi döndüren metotlar.”

class Rectangle {
    private int width, height;
    public void setWidth(int w) { width = w; }
    public void setHeight(int h) { height = h; }
    public int getWidth() { return width; }
    public int area() { return width * height; }
    public int perimeter() { return 2 * (width + height); }
}

Puanlama genelde şöyle: alanların private tanımı, her metodun doğru başlığı (dönüş tipi!), gövdede doğru formül, main’de new ile nesne oluşturup metotları nokta ile çağırmak. 3’e 4’lük bir dikdörtgende alan 12, çevre 14 çıkar.

Sık yapılan hatalar

Yanlış düşünceDoğrusu
Dog d; nesne oluştururSadece referans tanımlar; nesne new Dog() ile
Örnek metodu static yazılırÖrnek metotları static değildir
Account.getBalance()Nesne üzerinden: acc.getBalance()
Alanlar başlangıçta tanımsız, derlenmezVarsayılan değer alır: 0, null, false
İki nesne aynı alanları paylaşırHer nesnenin kendi kopyası
b = a; nesneyi kopyalarReferansı kopyalar; aynı nesne
a == b içerik karşılaştırırAynı nesne mi diye bakar
Alanlar public olsun, kolay olurprivate + get/set, doğrulama için
get metodu voidAlanın tipini döndürür
set metodu değer döndürürGenellikle void
null referansla metot çağrısı derlenmezDerlenir, çalışırken NullPointerException

Kendini test et

Sınavdaki gibi İngilizce sorular. Önce kâğıt kalemle çöz, sonra cevabı aç.

Soru 1kolay

Counter has a private int count, increment() adds 1 to it and getCount() returns it. What is printed?

Counter c1 = new Counter();
Counter c2 = new Counter();
c1.increment();
c1.increment();
c2.increment();
System.out.println(c1.getCount() + " " + c2.getCount());
Cevabı göster
2 1

İki ayrı new, iki ayrı nesne. Her nesnenin kendi count alanı var. c1'in sayacı 2, c2'ninki 1.

Soru 2orta

Using the same Counter class, what is printed?

Counter c3 = new Counter();
Counter c4 = c3;
c3.increment();
c4.increment();
c4.increment();
System.out.println(c3.getCount());
Cevabı göster
3

c4 = c3 yeni nesne oluşturmaz; ikisi de aynı nesneyi gösterir. Üç increment çağrısı aynı count'u artırır: 3.

Soru 3orta

deposit adds the amount only if it is positive; withdraw subtracts only if the amount is not more than the balance, otherwise it prints Insufficient funds. What is printed?

Account a = new Account();
a.deposit(300);
a.withdraw(100);
a.withdraw(250);
a.deposit(-20);
System.out.println(a.getBalance());
Cevabı göster
Insufficient funds
200.0

300 yatır → 300. 100 çek → 200. 250 > 200 → çekilmez, mesaj basılır. -20 pozitif değil → yok sayılır. balance double olduğu için 200.0 basılır.

Soru 4kolay

Dog has fields String name; and int age; with no initial values. What is printed?

Dog d = new Dog();
System.out.println(d.name + " " + d.age);
Cevabı göster
null 0

Örnek değişkenleri (instance variables), yerel değişkenlerin aksine varsayılan değer alır: nesne referansları (String) null, int 0. Bu yüzden derleme hatası yok.

Soru 5orta

What is printed?

class Box {
    private int size = 1;
    public void setSize(int s) { if (s > 0) size = s; }
    public int getSize() { return size; }
    public int volume() { return size * size * size; }
}
// in main:
Box bx = new Box();
bx.setSize(4);
bx.setSize(-2);
System.out.println(bx.getSize() + " " + bx.volume());
Cevabı göster
4 64

set metodu doğrulama (validation) yapıyor: -2 geçersiz, alan değişmez. size 4 kalır, hacim 4 * 4 * 4 = 64. private alanın asıl faydası bu: geçersiz değer içeri giremez.

Soru 6zor

Using Account (deposit adds positive amounts), what is printed?

Account p = new Account();
Account q = new Account();
p.deposit(100);
q = p;
q.deposit(25);
p = new Account();
p.deposit(5);
System.out.println(p.getBalance() + " " + q.getBalance());
Cevabı göster
5.0 125.0

q = p sonrası ikisi de ilk hesabı gösterir; 100 + 25 = 125. Sonra p yeni bir hesaba yönlendirilir (q hâlâ eskisinde) ve 5 yatırılır. q'nun ilk gösterdiği boş nesne artık kimse tarafından gösterilmiyor.

Soru 7kolay

Rectangle has private int width and height, setters, getWidth(), area() and perimeter(). What is printed?

Rectangle r = new Rectangle();
r.setWidth(3);
r.setHeight(4);
System.out.println(r.area() + " " + r.perimeter());
r.setWidth(r.getWidth() * 2);
System.out.println(r.area());
Cevabı göster
12 14
24

Alan 3 * 4 = 12, çevre 2 * (3 + 4) = 14. Genişlik get ile okunup 2 katı set edilir: 6. Yeni alan 6 * 4 = 24.

Soru 8kolay

What is printed?

class Light {
    private boolean on;
    public void toggle() { on = !on; }
    public boolean isOn() { return on; }
}
// in main:
Light l = new Light();
l.toggle();
l.toggle();
l.toggle();
System.out.println(l.isOn());
Cevabı göster
true

boolean alan false ile başlar. Her toggle tersine çevirir: true, false, true. boolean getter'lar geleneksel olarak is ile başlar: isOn().

Soru 9orta

balance is declared private in class Acc. Which statement in main (another class) does not compile, and why?

  1. Acc a = new Acc();
  2. a.balance = 1000;
  3. System.out.println(a.getBalance());
  4. a.deposit(50);
Cevabı göster
b

private bir alana sadece kendi sınıfının içinden erişilir. javac: balance has private access in Acc. Dışarıdan erişim public metotlarla (getBalance, deposit) yapılır.

Soru 10orta

What happens when this code runs?

Account n = null;
n.deposit(10);
Cevabı göster
NullPointerException at runtime

null, referansın hiçbir nesneyi göstermediği anlamına gelir. Derleyici tipe baktığı için kod derlenir, ama çalışırken olmayan bir nesnenin metodu çağrılınca NullPointerException fırlatılır.

Soru 11orta

Write the withdraw method of Account (private double balance): subtract amount only if it is positive and not more than the balance; otherwise print Insufficient funds.

Cevabı göster
if (amount > 0 && amount <= balance) balance -= amount; else System.out.println("Insufficient funds");

Örnek metodu (instance method) static değildir; doğrudan nesnenin alanını kullanır.public void withdraw(double amount) { if (amount > 0 && amount <= balance) { balance -= amount; } else { System.out.println("Insufficient funds"); }}Bu sayfadaki örnek sürüm sadece amount <= balance kontrol ediyor; negatif çekimi de engellemek için amount > 0 eklendi.

Soru 12zor

Write a class Thermostat with a private double celsius, a setter that accepts only values from 5 to 35 (inclusive), a getter, and a method getFahrenheit().

Cevabı göster
if (value >= 5 && value <= 35) celsius = value; · return celsius * 9 / 5 + 32;

class Thermostat { private double celsius; public void setCelsius(double value) { if (value >= 5 && value <= 35) celsius = value; } public double getCelsius() { return celsius; } public double getFahrenheit() { return celsius * 9 / 5 + 32; }}Test: setCelsius(45) reddedilir, getCelsius() → 0.0 (varsayılan). setCelsius(22.5) → 22.5, getFahrenheit() → 72.5. celsius double olduğu için * 9 / 5 int bölme tuzağına düşmez.

Doğrulama: Tüm çıktılar JDK 26 ile çalıştırıldı (verify/SEN1001/W10.java; Dog, Account, Thermostat, Counter, Box, Rectangle ve Light sınıfları aynı dosyada). withdraw yazma sorusunun cevabı W11.java içindeki Account2 sınıfında aynen çalıştırıldı. private erişim ve static bağlam hataları verify/SEN1001/err/priv/ altında javac ile alındı.

Deftere not kartı

Sınıf (class) = kalıp nesne (object) = new ile üretilen örnek (instance) Dog d = new Dog(); d bir REFERANS (nesnenin adresi), nesnenin kendisi değil Örnek değişkeni (field): sınıfın içinde, metotların dışında. Her nesnenin KENDİ kopyası Alan varsayılanları: int 0, double 0.0, boolean false, String/nesne null (yerel değişkenlerde yok!) Örnek metodu static DEĞİL: d.bark() static main'den Sinif.metot() ile çağrılamaz Nokta operatörü: nesne.alan, nesne.metot() private: sadece kendi sınıfından public: her yerden Kapsülleme: alanlar private, erişim public get/set ile getX() değer döndürür setX(v) değeri atar (+ doğrulama) boolean için isX() b = a → aynı nesne, b.metot() a'yı da değiştirir a == b aynı nesne mi? Hiçbir şeyi göstermeyen referans: null → metot çağrısı NullPointerException Bir dosyada tek public class, adı dosya adı; diğer sınıflar public olmadan aynı dosyada olabilir