OOP kullanmamızın nedeni, yazılım geliştirmeyi daha düzenli, güvenli ve sürdürülebilir hale getirmesidir.
OOP, dört temel ilkeye dayanır: kapsülleme, kalıtım, çok biçimlilik ve soyutlama. Bu ilkeler, yazılımın daha esnek, anlaşılır ve bakımı kolay olmasını sağlar.
- Kapsülleme, verilerin yalnızca belirli metotlarla erişilmesini sağlar.
- Kalıtım, kod tekrarını azaltır ve yeni sınıflar oluşturmayı kolaylaştırır.
- Çok biçimlilik, aynı metodun farklı nesnelerle farklı şekilde çalışmasını sağlayarak esneklik kazandırır.
- Soyutlama, karmaşık işlemleri basitleştirir.
Yaygın olarak kullanılan bazı OOP dilleri ise Java, C++, Python ve C#'tır.
| Interface | Abstract Class |
|---|---|
| Interface'lerin amacı nesneler için davranış belirlemektir. | Abstract class'ın amacı ise ortak bir işlevsellik sunmaktır. |
| "implements" ile uygulanırlar. | "extends" ile uygulanırlar. |
| Constructor içeremez. | Constructor içerebilir. |
| Yalnızca başka bir interface'i extend edebilir. | Başka bir sınıfı extend edebilir ve birden çok interface uygulayabilir. |
| Tüm metodlar abstract olmalıdır. Java 8'den sonrası static veya default metodlara da sahip olabilir. | Hem soyut (abstract) hem de somut metodlar olabilir. |
| Bir sınıf birden fazla interface implement edebilir, çoklu miras mümkündür. | Bir sınıf yalnızca bir abstract class’tan miras alabilir, çoklu miras mümkün değildir. |
"equals" ve "hashCode" metodları nesnelerin doğru bir şekilde karşılaştırılabilmesi ve HashMap, HashSet gibi koleksiyonlarda düzgün çalışabilmesi için gereklidir. "equals" nesneleri eşitlik açısından karşılaştırır, "hashCode" ise nesnelere benzersiz bir kimlik sağlayarak hash tabanlı koleksiyonlarda kullanılır.
Bu metodları nesneler için özel bir eşitlik kontrolü yapmak için veya nesneleri hash tabanlı koleksiyonlarda kullanıyorsak ve eşit olan nesnelerin aynı hashCode değerine sahip olmasını istiyorsak override etmeliyiz.
Diamond problemi, çoklu kalıtımın desteklendiği dillerde bir sınıfın iki farklı üst sınıftan aynı metodu miras alması durumunda hangi metodu kullanacağı belirsiz hale gelmesi durumudur.
Java’da sınıflar için çoklu kalıtım desteklenmez. Bu yüzden sınıflarla diamond problemi yaşanmaz. Ancak interface'lerle bu durum ortaya çıkabilir. Eğer iki interface aynı default metodu içeriyorsa alt sınıf bu metodu override ederek çakışmayı önlenebilir.
Java'da oluşturulan nesneler işlevleri bittikten sonra bellekten temizlenmelidir. Eğer temizlenmezlerse gereksiz bellek kullanımı oluşur ve bu durum zamanla belleğin dolmasına, performans düşüşüne ve hatta uygulamanın çökmesine neden olabilir. Garbage Collector bu tür sorunları önleyerek bellek yönetimini optimize eder.
Java'da nesneler heap bellekte saklanır ve referanslarla erişilir. Eğer bir nesneye artık erişilemiyorsa Garbage Collector bunu tespit eder ve belleği temizler. Bu işlem genellikle otomatik olarak gerçekleştirilir ancak Java Virtual Machine (JVM) gerektiğinde Garbage Collector'ı çalıştırır. Kullanıcı isterse System.gc() komutuyla da Garbage Collector'ı manuel olarak tetikleyebilir.
Java'da static anahtar kelimesi bir değişken, metod veya sınıfı sınıfa ait yapmak için kullanılır. Yani static ile işaretlenmiş bir şey sınıfın her nesnesi tarafından paylaşılır.
- Static değişkenler, sınıfın tüm nesneleri tarafından paylaşılır, her nesne kendi kopyasını kullanmaz.
- Static metodlar, sınıfın nesnesine ihtiyaç duymadan çağrılabilir.
- Static bloklar, sınıf yüklendiğinde bir kez çalıştırılır.
Immutability, bir nesnenin oluşturulduktan sonra değiştirilememesi durumudur. Yani nesne bir kez oluşturulduğunda içindeki veriler sabit kalır ve sonradan değiştirilmesi mümkün olmaz. Bu özellik nesnenin güvenliğini ve bütünlüğünü korur.
Where?
Immutability genellikle String gibi sınıflarda kullanılır. Örneğin Java'daki String sınıfı immutable'dır, yani bir String nesnesi oluşturulduktan sonra değeri değiştirilemez. Ayrıca çoklu iş parçacığına sahip uygulamalarda immutable nesneler tercih edilir çünkü değiştirilemez nesneler iş parçacıkları arasında güvenli bir şekilde paylaşılabilir.
How?
Immutability sağlamak için sınıflar final olarak tanımlanabilir ve değişkenler final ile sabitlenebilir. Bu sayede nesnelerin durumu oluşturulduktan sonra değiştirilemez.
Why?
Immutability, iş parçacığı güvenliği (thread-safety) sağlar çünkü bir nesnenin durumu değiştirilemez ve birden fazla iş parçacığı tarafından güvenle kullanılabilir. Ayrıca immutable nesneler hata yapma olasılığını azaltır, kodun anlaşılmasını kolaylaştırır ve bakımını basitleştirir.
Composition, bir nesnenin başka bir nesneye sahip olması ilişkisidir. Örneğin otomobil ve motor arasındaki ilişki composition’dur. Eğer otomobil yoksa, motor da yok olur.
Aggregation da bir nesnenin başka bir nesneye sahip olması ilişkisidir. Örneğin üniversite ve öğrenci arasındaki ilişki aggregation’dur. Bir öğrenci birden fazla üniversitede eğitim alabilir ve üniversite yok olsa bile öğrenci varlığını sürdürebilir.
Farklar:
Composition'da bağlılık güçlüdür; ana nesne yok olduğunda bileşen nesne de yok olur. Aggregation'da bağlılık daha zayıftır; bileşen nesne bağımsız olarak varlığını sürdürebilir. Yaşam Süresi:
Composition'da bileşen nesnenin yaşam süresi, ana nesnenin yaşam süresine bağlıdır. Aggregation'da bileşen nesne, ana nesneden bağımsız olarak var olabilir.
Cohesion bir sınıfın veya modülün sorumluluklarının ne kadar odaklanmış ve tutarlı olduğunu ifade eder. Örneğin bir Müşteri sınıfı yalnızca müşteri ile ilgili işlemleri yapmalı, başka işlevlerle karışmamalıdır.
Coupling ise sınıflar veya modüller arasındaki bağımlılıkları ifade eder.
Farklar:
Cohesion, bir sınıfın içindeki işlevselliği ifade ederken, Coupling sınıflar arasındaki ilişkiyi ifade eder.
Cohesion yüksek olduğunda sınıfın sorumlulukları daha net ve yönetilebilir olurken, Coupling yüksek olduğunda sınıflar arasındaki bağımlılıklar artar, bu da değişikliklerin diğer sınıfları etkilemesine neden olabilir.
Heap ve Stack, bellek yönetiminde kullanılan iki farklı alanı temsil eder.
Stack, programın çalışması sırasında kullanılan kısa süreli verilerin saklandığı alandır. Değişkenler burada saklanır ve fonksiyonlar çağrıldıkça yığına eklenir, fonksiyonlar bittiğinde ise otomatik olarak silinir.
Heap, Dinamik bellek tahsisi yapılan alandır. Burada nesneler ve uzun süreli veriler saklanır. Heap'teki veriler manuel olarak ya da garbage collector tarafından silinir.
Farklar:
Stack hızlıdır, çünkü veriler otomatik olarak düzenlenir ve silinir. Heap daha yavaştır ancak büyük veriler ve uzun ömürlü nesneler için uygundur.
Stack küçük ve kısa ömürlü verilere, Heap ise büyük ve uzun ömürlü verilere yöneliktir.
Exception, bir program çalışırken meydana gelen ve normal akışın bozulmasına yol açan hatalardır. Bu hatalar yazılımın beklenmedik durumlarla karşılaşması sonucu ortaya çıkar.
Types of Exceptions:
Checked Exceptions: Bunlar, programın çalışması sırasında ortaya çıkması muhtemel olan hatalardır ve derleyici tarafından kontrol edilir. Örneğin, IOException.
Unchecked Exceptions: Bunlar, genellikle yazılımın mantık hatalarından kaynaklanan hatalardır ve program çalışırken gözden kaçabilir. Örneğin, NullPointerException ve ArrayIndexOutOfBoundsException.
Basit, okunabilir, sürdürülebilir kod.
Java'da method hiding, bir alt sınıfın üst sınıftan miras aldığı bir statik metodu yeniden tanımlaması (overriding) işlemidir. Ancak, bu metot sadece alt sınıfın nesnesi üzerinden değil, sınıf ismi ile çağrıldığında üst sınıfın metodu kullanılır.
Abstraction ve Polymorphism, Java’daki iki temel nesne yönelimli programlama kavramıdır.
Abstraction , karmaşık bir sistemi basitleştirme işlemidir. Yalnızca gerekli bilgileri gösterir ve detayları gizler.
Polymorphism , bir nesnenin birden fazla biçimde davranabilme yeteneğidir. Aynı metod farklı nesnelerle farklı şekillerde çalışabilir. Örneğin bir Shape sınıfı ve bunun alt sınıfları olan Circle ve Square'da draw() metodu farklı şekilde çalışabilir.
Farklar:
Abstraction, ne yapılacağını belirlerken, Polymorphism nasıl yapılacağını belirler.
Abstraction daha çok sınıf yapısına odaklanırken, Polymorphism davranışların çok biçimli hale gelmesine olanak tanır.