Scala’da case classes, pattern eşleştirme ve exception handling

Evet arkadaşlar selamlar,

Bu blogda arada sırada Scala yazmaya çalışıyorum. Bu ay da Scala’nın bazı özelliklerinden kısaca bahsedeyim istedim. Bu yazıda case classes, kısaca pattern matching ve exception mantığından bahsedeceğim sizlere.

Case classes, normal class mantığından bir kaç sentaktik şeker vererek ayrılan bir olgu. Case class kullandığınız zaman constructorda verdiğiniz parametreler için otomatik olarak içerde private alanlar oluşturuluyor ve bu alanlara yine constructorda verdiğiniz parametre isimlerinden erişebiliyorsunuz. Bu sayede basit POJO lar oluşturmak oldukça kolay hale geliyor. Basit bir örnek vermek gerekirse:

case class Person(firstName: String, lastName: String)

val me = Person("Erkan", "Ahmet")
val first = me.firstName
val last = me.lastName

if (me == Person(first, last)) {
  println("Found myself!")
  println(me)
}

Gördüğünüz gibi bütün sınıf tek bir satırdan oluşmakta. Gerçi bu kavramın adındaki Case nedir diye düşünenleriniz vardır, az bekleyin.

Gelelim pattern matching’e. Java da bu mantık switch case ler üzerinden yürüyor bildiğiniz gibi. Yalnız bu yapı sadece primitif tipleri kontrol edebiliyor. Bu da sizi eninde sonunda bir integer a yada bir enum değerine kadar indirebiliyor. O kadar karmaşık sınıflar yazıyor ama karşılaştıramıyoruz.

Bu soruna Scala’da amcalar neşter atmışlar. Temelde Java’dan ayrıldığı bir kaç noktayı aktaralım:

  1. Case statementları birbiri içine girmezler, yani gidip de hepsine break yazmak zorunda değilsiniz.
  2. Case statementları bir değer dönerler, bunu olduğu gibi kullanabilirsiniz, bu sayede daha az satır kod yazmış olursunuz.
  3. Case statementlar, patternleri eşleştirebilirler, bunun en güzel örneği ise case class kullanımında görülür.

object Scenario{
def apply(user: String, action: GameElement) = {
action match {
case workout: Workout => new WorkoutScenario( workout, user )
case like: Like => new SocialScenario( like, user )
}
}
 }

 

 
Örnekte gördüğünüz üzere, action nesnesi match blokuna sokuldu. Match blokunda, bu action sınıfından türemiş diğer sınıflarla karşılaştırıldı. Bunlar Workout ve Like. Bunlardan hangisi ile eşleştiyse de, buna uygun bir nesne üretildi ve geri dönüldü. İşte ben buna factory pattern derim. Hatta demem, çünkü ortada pattern denecek kadar bir kod parçası yok. : )

Peki gelelim exception handlinge. Scala bu işe de el atmış durumda. Normalde bir noktadan exception throw ederdiniz. Burada sorun yok. Fakat yakalayacağınız yerde, her bir exception tipi için ayrı ayrı blok açar ve ne yapacağınızı şaşırdınız. Scala ise exception handling’de de pattern matching kullanarak, işimizi bir adım daha kolaylaştırıyor.

Örnek vermek gerekirse

</pre>
<address>try{

workoutItems.foreach(item => {
...
if (repeat <= set.repeat_number.toInt) {</address><address>              ....
throw BadgeWon("pushup badge won!")
}

})
}
})

}
catch {
case e:BadgeWon => println("found the badge: " + e.message)
case e => {
println("general exception" + e.getMessage )
e.printStackTrace()
}
}</address><address>
Gördüğünüz gibi çok daha kısa bir kod parçası ile, exceptionlarınızı da yönetmeyi başardınız. Scala kullandıkça özelliklerini daha da çok seveceksiniz.
Önümüzdeki yazıda function literals konusuna değinmek istiyorum, herkese iyi günler!