Java’da soyutlama kavramını nasıl anlatacağıma uzunca bir zaman karar veremedim. Yazılım prensiplerinden olan “Open – Closed” prensibinin temelini oluşturan bu konuyu kavramanın, bir yazılımcı için çok önemli olduğunu düşünüyorum.
Yazılım yaparken, bu dünyadaki işleri, bilgisayar bilimlerine uyarlamaya çalışırız. Sosyal hayatımızda farkında olarak veya farkında olmadan, bir çok ortak özelliği ve işleyişi gruplandırırız. Örneğin hayvanları seslerine, türlerine, tehlike düzeylerine, ayak sayılarına vs. göre sınıflandırırız. Bu sınıflandırmayı yeni bir canlı keşfedildiğinde, bütün özelliklerini tek tek yazmak yerine, sadece bir gruba dahil edip, o grup dan farklı olan özelliklerini yazmak için kullanırız. Dünya üzerindeki bütün hayvanların kayıtlarını tutacağımızı düşünelim. Her hayvan için, bunun solunum sistemi vardır, bunun sesi vardır veya bu türün üreme özelliği vardır demenin iş yükü büyük olacaktır. Bu yükten kurtulmak için “Hayvan” adında kafamızda bir tanım üretip, hayvanları bu tanım ile ilişkilendiririz. Bu sayede biri bir hayvandan bahsederken, hangi hayvan olursa olsun, üreyebildiğini, hareket edebildiğini, solunum yapabildiğini hemen düşünürüz. (üreme sisteminin, hareket sisteminin ve solunum sisteminin farklıklar gösterdiğini bilsekte) Bilgisayar biliminde Abstraction (soyutlama) tam da yukarıda anlatmak istediğimi, elektronik ortamda gerçekleştirmek için vardır.
Şimdi soyutlamayı java’da nasıl yapıyoruz onu inceleyelim.
abstract class Hayvan {
abstract void hayvaninSesi(); // Bir özellik / İşleyiş
}
class Kedi extends Hayvan {
void hayvaninSesi() {
System.out.println("Meyaaav");
//Sub class (alt sınıf) ihtiyaçlarına göre özellik / işleyiş implementasyonu
}
}
class Kopek extends Hayvan {
void hayvaninSesi() {
System.out.println("Hav Hav");
//Sub class (alt sınıf) ihtiyaçlarına göre özellik / işleyiş implementasyonu
}
}
Yukarıdaki örnekte görüldüğü gibi, super class dan gelen metotdlar, sub class içinde aynen kullanılmak zorunda değil. Her biri kendi işleyişini çalıştırabilir konumdadır. hayvanSesi() metodu, Kedi class’ında consola “Meyaaav” yazarken, Kopek class’ında Hav Hav yazıyor. Şimdi diğer konulara değinelim ve bilgileri daha da pekiştirelim.
Java’da soyutlama işlemi absctract sınıflar ve interfaceler kullanılarak yapılmaktadır. Bu yazımızda sadece Abstraction class’lar hakkında bilgi vereceğim. Bir sonraki yazımız ise tamamen interface’ler ile alakalı olacaktır. Her iki konuyu bu yazıya sığdırmaya çalışarak, can sıkıcı ve uzun bir paylaşım oluşmasını istemiyorum.
Abstract class’lar (Soyut sınıflar):
Abstract class’lar, abstract metodlar içerirler. abstract metod içeren bir abstract class’dan extend olan sub class’lar, abstract metodları implement etmek zorundadır. Bu cümlenin anlamını aşağıdaki satırları okumaya devam etmeniz halinde daha iyi anlayacaksınız.
Birazda abstract class ve abstract metotların oluşturulması ve kullanılması ile ilgili kurallardan bahsedelim.
- Abstrract class’lar ve abstract metotlar “abstract” anahtar kelimesi kullanılarak tanımlanılar. Abstract olarak tanımlanmış olan bu sınıflardan yeni nesneler (instance da diyebiliriz) oluştutamazsınız. Ama, abstract sınıfı implement eden alt class’lardan nesne oluştutabilir ve bu nesneyi abstract class türüne eşitleyebilirsiniz. Yani alt sınıflar üst sınıf değişkeni içine aktarılabilir ve hiç bir özellik kaybedilmez. Biliyorum cümle biraz karışık oldu. Hele ki kısaca konuya değinerek, bir şeyler anlatmaya çalşırken, cümle daha da işin içinden çıkılmaz bir hale geldi. JAVA hakkında temel konuları bitirdikten sonra “Yazılım Prensipleri” konusuna da değinmek istiyorum. Ancak şimdilik sadece araştırma yapmanız için, yukarıda anlatmak istediğim prensibin adını vererek yetineceğim. Araştırmanız gerelen prensip, “Liskov Substitution” prensibi. Aşağıdaki örneği inceleyerek bir çok fikir elde edebilirsiniz. Yine de “Liskov Substitution” prensibi hakkında biraz bilgi edinmeniz size bir çok fayda sağlayacaktır diye düşünüyorum. Hatta belli mi olur belki araştırmanızın ucu S.O.L.I.D. prensiplerine kadar gidebilir. Yinede siz benden duymuş olmayın
abstract class SoyutClass {
abstract void soyutMethod();
}
class SomutClass extends SoyutClass {
void soyutMethod() {
System.out.println("Soyut metot implement edildi.");
}
}
public class Soyutlama {
public static void main(String[] args) {
//SoyutClass A = new SoyutClass(); Abstract class'dan nesne oluşturulamaz
SomutClass C = new SomutClass();
//SomutClass abstract metodu implement eder,
//SomutClass'dan nesne oluşturabiliriz
SoyutClass A1 = C;
//SoyutClass'a somut class dan oluşturulmuş nesneyi verebiliriz. (Liskov subtitution prensibi)
}
}
- Abstract olmayan bir class içerisinde abstract bir metod tanımlaması yapılamaz. Ayrıca Abstract class içerisinde body kısmı yazılmamış ve abstract olmayan metot tanımlanamaz.
// Derleme zamanı hatası alınır.
class AbstractClass {
void abstractMethod(); //Standart bie class içerisinde body kısmı olmayan bir metod tanımlanamaz. Yanlış
abstract void abstractMethod(); //Abstract metod ancak abstract class içerisinde tanımlanabilir. Yanlış.
}
// ***** ***** ***** *****
// Bu kısım doğru
abstract class AbstractClass {
abstract void abstractMethod();
}
- Abstract class içerisinde abstract metod tanımlanmak zorunda değildir. Normal metodlarda kullanılabilir.
abstract class AbstractClass {
void metotBir() {
//somut metot
}
//Hiç abstract metot yok ancak class abstract. Sorun yok ;)
}
- İçersinde hiç abstract metod tanımlı olmasa bile, bir abstract class’dan nesne oluşturulamaz.
abstract class AbstractClass {
void metotBir() {
//somut metot
}
void metotIki() {
//somut metot
}
}
public class Abstraction {
public static void main(String[] args) {
AbstractClass a = new AbstractClass(); //Derleme zamanı hatası
//Hiç bir abstract metot barındırmasa bile, Abstract class'lardan nesne oluşturamazsınız.
}
}
- Bir abstract class içerisinde hem normal metot, hem de abstract metot tanımlaması yapılabilir.
abstract class AbstractClass {
void metotBir() {
//somut metot
}
void metotIki() {
//somut metot
}
abstract void metotUc(); //Soyut (abstract) metot
abstract void metotDort(); //Soyut (abstract) metot
}
- Abstract class’dan extend olan bütün sub class’lar, abstract olarak tanımlı olan metotları implement etmek zorundadır. Eğer implement edilmemiş abstract metod var ise o zaman class’ı abstract class’a çevirmek gerekir.
abstract class SoyutClass {
abstract void soyutMetotBir(); //Abstract metot
abstract void soyutMetotIki(); //Abstract metot
}
class SomutClass extends SoyutClass {
void soyutMetotBir() {
//soyutMetotBir() implement edildi
}
//eğer aşağıdaki metot implent edilmeseydi, class'ı abstract class haline dönüştürmek gerekecekti.
void soyutMetotIki() {
//soyutMetotIki() implement edildi.
//Super class içersindeki her iki abstract metot implement edildiği için SomutClass'ın abstract class'a dönüştürülme gerekliliği kalmamıştır.
}
}
- Abstract class içerisinde istediğiniz kadar constructor (yapıcı metot) bulunabilir.
abstract class AbstractClass {
AbstractClass() {
//Birinci constructor
}
AbstractClass(int i) {
//İkinci constructor
}
abstract void abstractMethodOne(); //Abstract Metot
}
- Abstract metotlar privite olarak tanımlanamazlar. Çünkü privite olarak tanımlı bir metot başka bir class içerisinde kullanılamaz.
abstract class AbstractClass {
private abstract void abstractMetotBir();
//Derleme zamanı hatası, abstract metot private olamaz.
}
- Constructor (yapıcı metotlar) ve field’lar abstract olarak tanımlanamazlar.
abstract class AbstractClass {
abstract int i;
//Derleme zamanı hatası, field'lar abstract olarak tanımlanamazlar.
abstract AbstractClass() {
//Derleme zamanı hatası, yapıcı metotlar abstract olarak tanımlanamazlar.
}
}
- Abstract metotlar statik olarak tanımlanamazlar.
abstract class AbstractClass {
static abstract void abstractMethod();
//Derleme zamanı hatası, abstract metodlar statik olarak tanımlanamazlar.
}
Sonraki makalemizde interface’lerden bahsedeceğiz.
Konu umarım anlaşılmıştır. Aklınıza takınlan bir konu olursa, lütfen yorum yazarak benimle iletişime geçiniz.
Tek Yorum
[…] Dün Java’da Abstraction (Soyutlama) hakkında yazdığım makalede belirttiğim gibi, javada kullanılan bir diğer soyutlama yöntemi olan arayüzlerden bahsedeceğim. […]