Java Intro Tutorial-TR
Herkese merhaba👋
Daha önceki oop-functional ve procedural yazımda kodlara detaylı değinemediğim için kısa bir Java tekrarı ile OOP kavramına değinmek istedim. Hadi başlayalım. 💪
Variables(Field or Attribute):
Variables(değişkenler) ile verileri tutarız. Neden variable’ları kullanıyoruz önce bunu anlamakta fayda var.
Diyelim ki okulda yoklama alınacak, ilk önce öğretmen sınıfta bulunan öğrenci sayısını kontrol ediyor, sonra müdür kontrol ediyor ve sonrasında toplam öğrenci sayısı sisteme işleniyor. Elimizdeki öğrenci sayısı başta 20 olsun. Sonradan sınıfa 1 öğrenci daha geldi ama listemiz çoktan müdüre gitmişti. Gidip tek tek o 1 öğrenciyi yoklama listemize ekleyip 21 olarak güncellememiz gerekecekti (hem de her kontrol sağlandığı yerde ve her gelen öğrenci de). Bu çok büyük bir külfet olurdu değil mi?
Tam da bu noktada değişkenleri(variables) kullanıyor olacağız.
✳️ DRY(Don’t Repeat Yourself): Object-Oriented tasarım prensip’i, kendinizi tekrar etmemek anlamına gelir. Bu da değişkenleri bir yerde tutup, herhangi bir güncelleme söz konusu olduğunda tek satır değişiklik ile tüm projeyi güncellemek anlamına gelir.
Projenin bir çok yerinde adres değişkenini kullandık ve bir adres değişikliği durumu gerektiğini varsayarsak böyle bir senaryoda yapmamız gereken tek şey adres satırını düzeltmek, aksi durumda adres verilerini yazdığımız her yerde elimizle tek tek adresleri güncellememiz gerekecekti.
Data Types:
Java, statik olarak yazılmış bir programlama dilidir. Bu, tüm değişkenlerin kullanılmadan önce bildirilmesi gerektiği anlamına gelir. Bu yüzden değişkenin türünü ve adını belirtmemiz gerekiyor.
Veri türleri, değişkende saklanabilecek farklı boyutları ve değerleri belirtir.
Değişken tanımlarken değişken içinde saklayacağımız veriyi belirlemek için kullanılır.
Java’da iki tür veri türü vardır:
1. Primitive data types(İlkel tipler):
8 tane primitive tip vardır. Bunlar:
✳️boolean, char, byte, short, int, long, float ve double.
2. Non-primitive data types(Referans tipler):
3 tane referans(non-primitive) tip vardır. Referans veri türleri arasında Sınıflar(classes), Arayüzler(Interfaces) ve Diziler(Arrays) bulunur.
Not: Stringler istisna olarak referans tiplere girmektedir.
✳️Bu iki veri tipi belleğin stack ve heap adlı bölgelerini kullanırlar. Değer tipleri stack’te tutulurken referans tipleri heap’de tutulur. Stack heap’e göre daha hızlıdır.
Biraz daha açalım bu konuyu.
✳️Primitive tipler için;
sayı1, sayı2'ye eşitlendi ve artık değeri stack’e 40 olarak yazıldı. Bu atamadan sonra sayı2'nin güncellenmesi sayı1'e etki etmez, sadece sayı2'nin yeni değeri 90 olarak güncellenir(şekildeki gibi).
✳️Referans tipler için;
Burada ki durum ise sayılar1'in adresi, sayılar2'nin adresine eşitleniyor. 1 ve 2 numaralı adresler olduğunu varsayalım. İlk sayılar1 listesi 1 nolu adreste tutulurken sayılar2 listesi 2 nolu adreste tutuluyor. Sayılar1'i sayılar2'e eşitleyince artık sayılar1'in adresi 2 numaralı adres oluyor. 1 numaralı adres artık değişken tutmadığı için çöp toplayıcısı(Garbage Collector) ile temizleniyor.
Stack bellekteki veri hemen silinirken Heap bellekteki verinin silinmesi Garbage Collector’a (Çöp toplama mekanizmasına) bağlıdır.
Conditions and if Blocks:
if bloklarını projelerimizde belli bir şarta göre dallandırmak için kullanırız.
Java, matematikteki mantıksal koşulları destekler.
Switch/Case Blokları:
Yürütülecek birçok kod bloğundan birini seçmek için switch bloklarını kullanırız.
For Loops:
Bir kod bloğu üzerinden kaç kez döngü yapmak istediğinizi tam olarak bildiğinizde for döngüsünü kullanabilirsiniz. For döngüsü 3 parametre alır.
Syntax:
Arrays(Diziler):
Aynı tipten çok sayıda değişken tanımlamak için kullanılır. Referans tiplerdir.
İndeks numarası 0 dan başlar.
✳️ []
Operatörü array adının sonuna getirilir ve bu operatör index numaralarını belirler.
String:
String karakter dizilerinin (char array) yerine geçer.
String bir ilkel(primitive) veri tipi değil, bir sınıftır(class). Kendi değişkenleri(variables) ve kendi metotları vardır.
Not: Boşluk da bir karakterdir.
String sınıfı java’da çok önemli rol oynar. O nedenle, Java API ‘de tanımlı String sınıfının 10 dan fazla constructor’ı ve 100 den fazla metodu(concat,replace,contains…) vardır. Bunlara bu yazıda değinmeyeceğim.
Variable(Değişken) Arguments (Varargs):
Değişken uzunluklu bir bağımsız değişken, üç nokta (…
) ile belirtilir. Belirli bir argüman türünün kaç tanesinin metod’a aktarılacağını bilmediğimizde varargs
kullanabiliriz. Burada önemli olan şey parametre olarak bir varargs kullanıyorsak bunu son parametre olarak yazmalıyız.
myMethod (int i, String ... strings) // truemyMethod (String ... strings, int i) // false
Metods:
Metotlar kodların küçük parçalara bölünmüş halidir. Kod tekrarlarını önlemek için oldukça faydalılardır. Bu sayede kod okunabilirliği ve kod performansı açısından büyük avantaj sağlarlar. Metotlar kullanıldığı dillere göre fonksiyonlar
, prosedürler
vb. olarak da adlandırılırlar.
Metotlar 2 kısımda incelenirler, detaya girmeden kısa örnek vereceğim.
🟣Parametreli metotlar
Parametre olarak Product
objesi alan addToCart adlı metot, sepete ürün(product) ekleme işlemini gerçekleştirmek amacıyla örnek olarak oluşturulmuştur.
🟣Parametresiz metotlar
Bu örnekte ise sepeti silme işlemini gerçekleştiren parametresiz bir metot(deleteCart) örneği verilmiştir.
Class:
Classlar referans tiplerdir.
Ortak operasyonları ve değişkenleri(field, attribute) tutarlar.
Büyük harfle başlarlar.
Bir class’ı kullanabilmek için initialize
işlemi yapmamız gerekiyor. Yani new’leyerek yeni bir nesne oluşturmalıyız.
Java’da classlar Static
yapılamazlar, ancak iç içe classlarda içteki class static yapılabilir.
Encapsulation:
Encapsulation için verileri private yaparız ve bu verilere erişmek için getter, setter metotlarını uygularız. Detaylı açıklama için bu yazıma bakabilirsiniz.
Bir Product sınıfı oluşturup, bu sınıfa özellikler ekledik. Erişebilmek için ise getter ve setter metotlarını ekleyip buradaki görevimizi bitirdik.
Main’de Product
sınıfını kullanırken, ya product1 gibi parametreli constructordan bir instance oluştururuz, ya da product2 gibi parametresiz constructordan bir instance oluşturup kullanırız.
Inheritance(Miras):
En temel olarak, bir projede ortak olan fieldları ve metotları tekrar tekrar yazmamıza gerek kalmadan, ortak olanları bir sınıfta toplayıp bu sınıftan miras alabilmeyi sağlar. Ayrıntılı açıklama için bu yazıma bakabilirsiniz.
Burada basit bir şekilde aktarmak istediğim için çok basic bir örnek oluşturdum. Ortak bir Customer sınıfımız var ve bu sınıfımız her müşteride olması gereken özellikleri tutar, yani base class olarak Customer’ı alacağız.
Bireysel ve kurumsal müşteriler kendilerine ait özellikleri dışında, base class’dan extends edilerek, base class özelliklerini de barındırmış olurlar. Kodun detayı için github’a bakabilirsiniz.
Polymorphism:
En basit tanımıyla çok biçimlilik demektir. Aralarında bir inheritance olan referans tiplerin birbirinin referansını tutması durumudur.
Bir başka tabirle inherit veya implemente edilen bir nesne üzerinden farklı biçimde ki inheritance veya implementasyonları kullanma yöntemidir. Genel olarak polimorfizm’i interfaceler ile kullanırız. Şimdi örnek üzerinden anlamaya çalışalım.
Diyelim ki birden fazla database ile çalışıyoruz, senaryomuzda her müşteri belirli isterlere göre MySQL, MSSQL ve Oracle database’lerinde tutulsun.
Burada bir interface oluşturup basit bir müşteri ekleme özelliği vereceğim.
ICustomerManager
interface’ini MySQL class’ında imlements edelim. Basit bir log yazdıralım.
Manager sınıfımda ICustomerManager
interface’ini parametre olarak vereceğim ve böylece addCustomer
metodunu istediğim database üzerinden gerçekleştirebileceğim.
Şimdi son olarak bunu main’de nasıl kullanacağımıza bakalım.
Görüldüğü üzere bir CustomerManager
nesnesi oluşturduk ve parametre olarak MySQL database’ine müşteri eklemek istediğimizi belirttik. Çalıştırdığımız zaman MySqlDbManager
class’ında yazdırdığımız log’u görebiliriz.
Abstract:
Zorunlu metotlar eklememizi sağlar, bu sayede her extends
edildiği class da metodumuz doldurulmaya zorlanır(resimdeki gibi). abstract
anahtar kelimesi ile kullanılır. New
ile kullanılamazlar.
Kodlamada en önemli şeylerden biri if’lerden kaçınmak diyebiliriz. Bir database yönetimi yaptığımızı düşünelim ve müşterilerin dataları farklı farklı databaseler de olsun. Bu kodu if ile yazacak olsaydık aşağıdaki gibi olurdu ve bu çok da iyi bir yöntem sayılmaz.
Abstract bir base class oluşturup bu class’dan istediğimiz bütün database’leri türetebiliriz, bu sayede kod review, edit işlemleri çok daha kolay bir hale gelmiş olacaktır. Burada sadece 1 tane örnek class MsSqlDbManager
paylaşacağım detaylı incelemek için github hesabıma bakabilirisiniz.
Extends ettiğimize göre bir de müşteri yönetim sınıfı oluşturup base class’ımız ile ilişkilendirelim. Böylece tek bir class üzerinden bütün projeyi ayağa kaldırmış olacağız ve başka hiçbir class’a bağımlı olmamış olacağız. Main class’ımızda artık istediğimiz database üzerinden işlem yapabiliyor olduk. Main elbette daha efektif yazılabilir ancak şuan konuyu dağıtmamak adına bu şekilde kullandım.
Interface:
Interfaceler class olarak kabul edilmezler fakat normal classlar veya abstract classlar gibi referans tutarlar. New
ile kullanılamazlar.
İsimlendirme kuralı olarak class adı önüne “I” eklenir bu şart değil ama genel olarak böyle kullanılır.
Not: Bir class birden fazla interface’i implements edebilir.
Not: Bir interface başka bir interface’i extends edebilir ama implements edemez.
Yine database örneği ile interface yapısını kuralım. Öncelikle bir interface
(ICustomerManager) oluşturacağız ki şablon görevi görsün.
Daha sonra implements edeceğimiz, müşteri datalarımızın olduğu veritabanlarının sınıflarını oluşturalım. Yine sadece 1 tane ekliyorum.
Son olarak main’de istediğim database’i ekleyip run ediyorum. Genel mantık en basit şekilde böyle.
Umarım faydalı olmuştur. Bir sonraki yazımda görüşmek üzere. 🙋