Kotlin’de Sınıflar (Kotlin Classes)

Tuğba KILIÇ
5 min readApr 12, 2020

--

Merhabalar bu yazımda sizlere Kotlin’de Sınıfları anlatacağım.

Sınıflar; bir durum hakkındaki verilerin bulunduğu yapılardır. Örneğin; arabalar hakkında bir sınıf oluşturmak istiyorsak bu sınıfta, arabaya dair kullanacağımız özelliklerin verilerin tutulmasını, olmasını isteriz. Yani arabanın modeli, markası, yakıt türü, üretim yılı, rengi, hacmi, motor gücü gibi özelliklerini tutan bir kutu olarak düşünebiliriz.

Sınıf(class) tanımlamasına örnek verecek olursak;

class Araba { }

Sınıflar içerisinde yapıcılar vardır bunlar constructor olarak adlandırılır. Kotlin’de 2 tane constructor bulunmaktadır.; Primary(birincil) ve Secondary(ikincil) constructorlar. Kotlin’de contructorlar Sınıf ismin yanına yazılır fakat Java’da Sınıf içine yazılırlar.

Primary Constructor(Birincil yapıcı)

Class başlığının bir parçası gibi olan constructorlardır.Class tanımlamasının hemen sonunda yer alırlar. Aşağıdaki gibi parametre ve tipi verildiği gibi default(varsayılan) değer ataması da yapılabilir.

class Araba constructor(arabaTİpi : String){
//
{
class Araba constructor(arabaTipi : String = "Default değer"){
}

Yukarıdaki constructorları çağıralım bir sınıf içerisinden;

fun main(){
val arabaBilgisi = Araba() //ikinci constructorı çağırır, defaultu
val arabaBilgisi2 = Araba(arabaTipi : "MiniCooper") // ilk contructorı çağırır
}

Secondary Constructor(İkincil yapıcı)

Birden fazla parametresi olan yapıcı yani constructorlardır. Secondary constructorlar; eğer bir classta primary constructor var ise onları işaret etmek zorundadırlar (this()).

class Araba(arabaTipi : String = “default constructor”){constructor(arabaTipi : String, rengi : String):this(){
//yukarıda birincil yapıcı olduğu için ikinci yapıcı onu göstermek için this kullandı.
}

Primary constructor olmadan örnek verecek olursak;

class Araba{ constructor(arabaTipi : String,  rengi : String){//ikincil yapıcı
}
}

Classlar yani Sınıflar default(varsayılan) olarak final’dır. Yani değiştirilemezdir.Biz bu sınıfları Open anahtar kelimesi ile Open yapabiliriz. final olan classtan miras(kalıtım) alamayız.Çünkü final yani erişilemez. Open yaparak bu sınıfı açık hale getirebiliriz.

Şimdi küçük bir Java-Kotlin karşılaştırması yapalım:)

Java                               Kotlin
classların default değeri private classların default değeri public
Erişim belirteçleri Erişim belirteçleri
Public Public
Protected Protected
Private Private
- internal

Sınıflar oluşturulurken onlara Erişim Belirteçleri verilir. Bu erişim belirteçleri ile Sınıflara erişilip erişilemeyeceği veya nasıl erişileceği bilgileri verilir. Aşağıda bu belirteçler ve açıklamaları yer almaktadır.

Private; Sınıf dışından erişim yasak demektir. Sadece tanımlandığı sınıf içinden erişilebilir.

Public; erişime açık demektir. Tanımlandığı sınıf ve diğer sınıflar kolayca erişilebilir.

Protected; Sadece tanımlandığı sınıf ve o sınıfı miras alanlar tarafından erişilebilir.

internal; Tanımlandığı modül içerisinden erişilebilir.

1-Data Class

Verilerin tutulduğu, saklandığı sınıflardır. Örneğin, bir ekranımız olsun ve bu ekranda üniversitelerin bilgileri olsun. Yani her bir alan(item) için bir üniversitenin adı, kurulma tarihi, rektör adı, bulunduğu şehir, fakülte sayısı gibi bilgiler olsun. Bu bilgilerin tanımlanarak tutulduğu bir kutu olarak düşünebiliriz.

Data Class özelliklerine değinecek olursak;

  • Data Class’lar Abstract, Open, Sealed, inner olamazlar.
  • Önünde data keywordü(anahtar kelimesi) olmak zorundadır.
  • Primary constructorı olmalıdır.
  • Yani en az bir değişkeni olmalıdır.
  • Bu değişkenler var-val olmalıdır.
  • Herhangi bir Class miras alınabilir.
  • interface implement edilebilir.

Özünde 4 tane fonksiyonu vardır ve bu fonksiyonlar primary constructor için çalışır.

  • toString
  • equals
  • hashcode
  • copy

Şimdi Kotlin’de Data Class tanımlamamızı yapalım.

data class YazarlarModel(
val profilePhotoLink: Int,
val kitapAdi: String,
val yazarAdi: String,
val yazarUlkesi: String,
val konu: String
)

Data Class’lara default yani varsayılan değer ataması yapılabilir.

data class AccountData(
val accountName: String = "",
val accountSurname: String = "",
val accountType: String = "Default Value",
val brancName: String = "Default Value",
val branchCode: String = "Default Value",
val brancNumber: String = "Default Value"
)

Bir Data Class’ı çoklamak istediğimizde onu kopyalayabiliriz. Bu durumda “copy” fonksiyonunu kullanırız. Yukarıdaki Data Class’ımızı aşağıdaki örnek ile kopyalıyoruz ve sadece Name değişkenine değer atıyoruz.Aşağıdaki kod ile Name’i sadece Ayşe yap ve diğer tüm bilgileri kopyala diyoruz. Böylece Data Class’tan verileri koplayarak, oluşturduğumuz nesnemize atıyoruz.

var copyAccountData: AccountData = accountDataInstance1.copy("Ayşe")

Aynı şekilde kopyalamadan da Data Class’tan yeni bir nesne oluşturularak istediğimiz değer atamaları yapılabilir.

val accountDataInstance2 = AccountData(
"Ertuğrul",
"Selami",
"BankAccount",
"Kadıköy",
"0024",
"325235"
)

2-Enum Class

Kodun daha okunabilirliğini sağlayan yapılardır. Enum Class tanımlaması aşağıdaki şekilde yapılır.

enum class DirectionType{ EAST, WEST, SOUTH, NORTH}

Enum class özelliklerine değinecek olursak;

  • Değişkenlerine nesne oluşturarak değil Enum adı ile erişilebilir.
  • Name ve ordinal değişkenleri default olarak final olduğu için, override edilemezler.
  • Abstract, Open, Sealed, inner, data olamazlar.
  • open classları extend edemezler.
  • interface’leri implement edebilirler.

Yukarıda tanımlanan Enum Class’a aşağıdaki şekillerde erişebiliriz.

fun main(){
DirectionType.EAST
}
veyafun main(){setDirection(DirectionType.East.Name)val redirectionType = when (directionType) {
DirectionType.EAST -> {
DirectionType.EAST.toString()
}
DirectionType.WEST -> {
DirectionType.WEST.toString()
}
DirectionType.NORTH -> {
DirectionType.NORTH.toString()
}
DirectionType.SOUTH -> {
DirectionType.SOUTH.toString()
}
}

3-Sealed Class

Sealed Class’lar Enum class’ların daha iyileştirilmiş halidir. Uygulamalardaki Adapter yazımında liste elemanları için vs. kullanılabilirler. Aşağıda Sealed Class örneği verecek olursak;

sealed class Fruit {
class Apple : Fruit()
class Banana : Fruit()

object GetFruit : Fruit() {
fun getFruit(): Fruit {
return Apple()
}
}
}

Yukarıdaki Fruit Class’ının alabileceği değerleri Apple ve Banana sınıfları ile sınırlandırıyoruz.

//print fonksiyonu oluşturuyoruz
fun printFruit(fruit: Fruit) {
when (fruit) {
is Fruit.Apple -> {
println("Apple")
}
is Fruit.Banana -> {
println("Banana")
}
Fruit.GetFruit -> {
print("Apple + Banana")
}
}
//main fonksiyonunu yazıyoruz
fun main() {
val apple = Fruit.Apple()
val banana = Fruit.Banana()
val getFruit = Fruit.GetFruit

printFruit(apple)
printFruit(banana)
printFruit(getFruit)
}

4-Nested ve Inner Class’lar

Nested Class’lar; iç içe classların yer aldığı yapıdır. Inner class ise; başka bir classın üyesi olan classtır. Aşağıda bu iki classın karşılaştırılması yapılmıştır.

Nested(iç içe sınıflar)           inner(dahili sınıflar)
-outer classın ismi kullanılır -nesne oluşturulmalı hem outer
hem de kendi classın nesnesi
oluşturuldu.
-outer yani dış class değişkenine -outer class değişken ve
erişemeyiz fonksiyonlarına erişirlir.

Nested Class’a (iç içe olan classlara) örnek verecek olursak;

class School{

private val schoolName = "Codemy"

class LawSchool {
val studentCount: Int = 5000

fun printOuterName() {
println("Outher School Name : $schoolName")
}
}

Inner Class’a örnek verecek olursak;

class School{

inner class MedSchool{

val studentCount: Int = 5000

fun printOuterName() {
println("Outher School Name : ${schoolName}")
}

inner class TechSchool : Shape()
}
}

Önemli Notlar

  • inner classlar dış classın yani miras aldığı classın herşeyine erişirler.
  • Eğer inner class herhangi bir classı extend ederse; mesela shape() classı extend etsin. Bu şekilde inner class hem outer(dış) hem de shape() classın özelliklerine erişebilirler. Yani multiInheritance yapmış olunur.
  • MultiInheritance(çoklu miras-kalıtım) Java’da olduğu gibi Kotlin’de de yasak fakat bu şekilde extend edilmiş classlara erişilerek bu işlem gerçekleştirilebilir. İnner classlarda bu şekilde multiInheritance ile birden fazla sınıf extend edilmiş yani bu sınıfların nesnesi yaratılmış olur. Bu da Memory(bellek) şişmesine sebep olur.

Nested (lawSchool) ve inner (medSchool)classlar main içinde farklı çağırırlar. Nested yani iç içe classları çağırmak için; sadece dış classın ismini kullanıyoruz. Inner classları çağırmak için ise; dış classın ve inner classın nesnesini oluşturarak çağırma işlemi yapıyoruz.

fun main() {

val lawSchool = School.LawSchool() //dış class ismi.Nested class
lawSchool.printOuterName()
lawSchool.studentCount

val medSchool = School().MedSchool() // dış class nesnesi.inner class nesnesi
medSchool.studentCount
medSchool.printOuterName()

val techSchool = School().MedSchool().TechSchool()//inner içindeki inner class olduğu için dış class nesnesi, inner class nesnesi ve kendi nesnesi ile çağırılabiliyor.
}
  • Dış yani outer classtaki değişkenler private olsa bile inner class bu değişkene kendi classı içindeymiş gibi erişebilir. Nested classlar zaten dış class değişkenlerine erişemezler.
  • Inner class ölmeden outer class nesnesi Memory’de yok edilmez. Çünkü dış classın bir referansı inner classsta tutuluyor. Yani inner class, dış classın tüm değişkenlerini içinde tutuyor aslında. Bu yüzden inner class ölmeden dış classın nesnesi ölmez. Yani inner classlar bellek şişmesini önlemek için dikkatli kullanılmalı.
  • inner classın nesnesi ne zaman silinirse dış classın nesnesi de o zaman silinir.

Not : Sınıfların en önemli konusu kalıtımdır. Kalıtım(inheritance) bir sınıfın başka bir sınıfa(erişilebilir ise, erişim belirteçleri sayesinde bunu anlayabiliyoruz) erişerek o sınıfın değişken, fonksiyonlarını kullanabilmesidir. Aşağıda kısaca tanımını göstereceğim.Detaylı olarak araştırmanızı tavsiye ederim.

class Ev(){
//
}
class Oda : Ev(){ // ev sınıfını miras aldık
//
}

Umarım faydalı bir yazı olur sizler için. Bilgilerimi tazeledikçe yazılarımı güncellemeye ve içerik üretmeye devam edeceğim.

Dipnot : Bu bilgileri öğrenmemiz için bize zaman ayıran, Bilişim sektörünün en sevilen arkadaş, mühendis ve hocalarından olan Gökhan Öztürk’e teşekkürlerimi iletmeyi bir borç bilirim.

--

--