Podudaranje uzoraka je mehanizam za provjeranje da li vrijednost odgovara uzroku. Uspješno podudaranje može također i dekonstruisati vrijednost na njene dijelove. Ono je moćnija verzija switch
izjave u Javi tako da se može koristiti umjesto serije if/else izjava.
Sintaksa
Izraz za podudaranje ima vrijednost, match
ključnu riječ, i bar jednu case
klauzu.
import scala.util.Random
val x: Int = Random.nextInt(10)
x match {
case 0 => "zero"
case 1 => "one"
case 2 => "two"
case _ => "many"
}
val x
iznad je nasumično odabrani integer između 0 i 10.
x
postaje lijevi operand match
operatora a na desnoj strani je izraz s četiri slučaja.
Zadnji slučaj, _
, je “uhvati sve” slučaj za brojeve veće od 2.
Slučajevi se još zovu i alternative.
Izrazi za podudaranje imaju vrijednost.
def matchTest(x: Int): String = x match {
case 1 => "one"
case 2 => "two"
case _ => "many"
}
matchTest(3) // many
matchTest(1) // one
Ovaj izraz za podudaranje ima tip String
jer svi slučajevi vraćaju String
.
Stoga, metoda matchTest
vraća String
.
Podudaranje case klasa
Case klase su posebno korisne za podudaranje uzoraka.
abstract class Notification
case class Email(sender: String, title: String, body: String) extends Notification
case class SMS(caller: String, message: String) extends Notification
case class VoiceRecording(contactName: String, link: String) extends Notification
Notification
je apstraktna nadklasa koja ima tri konkretna tipa implementirana kao case klase Email
, SMS
, i VoiceRecording
.
Sada možemo podudarati uzorke s ovim case klasama:
def showNotification(notification: Notification): String = {
notification match {
case Email(email, title, _) =>
s"You got an email from $email with title: $title"
case SMS(number, message) =>
s"You got an SMS from $number! Message: $message"
case VoiceRecording(name, link) =>
s"you received a Voice Recording from $name! Click the link to hear it: $link"
}
}
val someSms = SMS("12345", "Are you there?")
val someVoiceRecording = VoiceRecording("Tom", "voicerecording.org/id/123")
println(showNotification(someSms)) // prints You got an SMS from 12345! Message: Are you there?
println(showNotification(someVoiceRecording)) // you received a Voice Recording from Tom! Click the link to hear it: voicerecording.org/id/123
Metoda showNotification
prima parametar tipa Notification
i podudara tip Notification
(tj. traži da li je to Email
, SMS
, ili VoiceRecording
).
U slučaju case Email(email, title, _)
polja email
i title
se koriste za povratnu vrijednostali se body
ignoriše s _
.
Čuvari uzoraka (en. guards)
Čuvari uzoraka su jednostavno boolean izrazi koji se koriste za preciziranje uzorka.
Samo dodajte if <boolean expression>
nakon uzorka.
def showImportantNotification(notification: Notification, importantPeopleInfo: Seq[String]): String = {
notification match {
case Email(email, _, _) if importantPeopleInfo.contains(email) =>
"You got an email from special someone!"
case SMS(number, _) if importantPeopleInfo.contains(number) =>
"You got an SMS from special someone!"
case other =>
showNotification(other) // nothing special, delegate to our original showNotification function
}
}
val importantPeopleInfo = Seq("867-5309", "[email protected]")
val someSms = SMS("867-5309", "Are you there?")
val someVoiceRecording = VoiceRecording("Tom", "voicerecording.org/id/123")
val importantEmail = Email("[email protected]", "Drinks tonight?", "I'm free after 5!")
val importantSms = SMS("867-5309", "I'm here! Where are you?")
println(showImportantNotification(someSms, importantPeopleInfo))
println(showImportantNotification(someVoiceRecording, importantPeopleInfo))
println(showImportantNotification(importantEmail, importantPeopleInfo))
println(showImportantNotification(importantSms, importantPeopleInfo))
U case Email(email, _, _) if importantPeopleInfo.contains(email)
, uzorak se podudara samo ako je email
u listi važnih ljudi.
Podudaranje samo tipa
Možete podudarati samo tip ovako:
abstract class Device
case class Phone(model: String) extends Device {
def screenOff = "Turning screen off"
}
case class Computer(model: String) extends Device {
def screenSaverOn = "Turning screen saver on..."
}
def goIdle(device: Device) = device match {
case p: Phone => p.screenOff
case c: Computer => c.screenSaverOn
}
def goIdle
ima različito ponašanje zavisno od tipa Device
.
Ovo je korisno kada uzorak mora pozvati metodu na uzorku.
Konvencija je da se koristi prvo slovo tipa kao identifikator (p
i c
ovdje).
Zapečaćene klase (en. sealed)
Trejtovi i klase mogu biti sealed
što znači da svi podtipovi moraju biti reklarisani u istom fajlu.
Ovo osigurava da su svi podtipovi poznati.
sealed abstract class Furniture
case class Couch() extends Furniture
case class Chair() extends Furniture
def findPlaceToSit(piece: Furniture): String = piece match {
case a: Couch => "Lie on the couch"
case b: Chair => "Sit on the chair"
}
Ovo je korisno za podudaranje tipovajer nam ne treba “catch all” slučaj.
Napomene
Scalin mehanizam podudaranja uzoraka je najkorisniji za algebarske tipove koji su izraženi kroz case klase.
Scala također dozvoljava definisanje uzoraka nezavisno od case klasa, koristeći unapply
metode u ekstraktor objektima.
Contributors to this page:
Contents
- Uvod
- Osnove
- Sjedinjeni tipovi
- Klase
- Podrazumijevane vrijednosti parametara
- Imenovani parametri
- Trejtovi
- Tuples
- Kompozicija mixin klasa
- Funkcije višeg reda
- Ugniježdene metode
- Curry-jevanje
- Case klase
- Podudaranje uzoraka (pattern matching)
- Singlton objekti
- Regularni izrazi
- Ekstraktor objekti
- For komprehensije
- Generičke klase
- Varijanse
- Gornja granica tipa
- Donja granica tipa
- Unutarnje klase
- Apstraktni tipovi
- Složeni tipovi
- Self-tipovi
- Implicitni parametri
- Implicitne konverzije
- Polimorfne metode
- Lokalno zaključivanje tipova (type inference)
- Operatori
- By-name parametri
- Anotacije
- Packages and Imports
- Package Objects