Məzmuna keç
Educora
İrəli24 dəq7 / 14

Siniflər, data siniflər, varislik və interfeyslər

Verilənləri və davranışı bir yerdə birləşdir: siniflər, konstruktorlar, data siniflər, `object` və companion obyekt, `open` ilə varislik və interfeyslər.

Özünü yoxla
Bu dərsdə öyrənəcəksən
  • Əsas konstruktoru, xassələri və metodları olan sinif yazmaq
  • Data sinfin verdiyi toString, ==, copy imkanlarından istifadə etmək
  • object və companion obyektin nə üçün lazım olduğunu izah etmək
  • open/override ilə varislik qurmaq və interfeysi reallaşdırmaq

Elektron jurnal yazırsan: hər şagirdin adı, sinfi və qiymətləri var, onlara yeni qiymət əlavə etmək və orta balı hesablamaq lazımdır. 30 şagird üçün ayrı-ayrı dəyişənlər tez bir zamanda qarışıqlığa çevrilir. Obyektyönlü proqramlaşdırma başqa yol təklif edir: verilənləri və onlarla işləyən funksiyaları bir yerdə — obyektdə birləşdirmək. Kotlin bunu çox qısa yazılışla edir.

Sinif, konstruktor və xassələr

Sinif obyektlərin çertyojudur, obyekt isə onun əsasında yaradılmış konkret nüsxədir. Kotlin-də sinif adından sonra mötərizədə əsas konstruktor yazılır: orada val və ya var ilə elan olunan parametrlər dərhal sinfin xassələrinə çevrilir. Sinfin içindəki funksiyalar metodlar adlanır. Obyekt new sözü olmadan, funksiya kimi yaradılır: Student("Aysel", 8).

Kotlin
class Student(val name: String, var grade: Int) {
    val scores = mutableListOf<Int>()

    fun addScore(score: Int) {
        scores.add(score)
    }

    fun average() = scores.average()

    fun introduce() = "I am $name, grade $grade"
}

fun main() {
    val aysel = Student("Aysel", 8)
    aysel.addScore(5)
    aysel.addScore(4)
    println(aysel.introduce())
    println(aysel.scores)
    println(aysel.average())
    aysel.grade = 9
    println(aysel.introduce())
}
Gözlənilən nəticə
I am Aysel, grade 8
[5, 4]
4.5
I am Aysel, grade 9
grade var olduğu üçün dəyişdirilə bilər, name isə val-dır və dəyişmir.

Data siniflər

Adi sinfin obyektini çap etsən, Student@1b6d3586 kimi anlaşılmaz mətn görəcəksən, eyni məlumatlı iki obyekt isə == ilə bərabər sayılmayacaq. Çox vaxt sinif sadəcə məlumat saxlamaq üçündür — istifadəçi, məhsul, sifariş. Belə hallarda sinfin qarşısına data sözü yazılır və Kotlin avtomatik olaraq oxunaqlı toString, məzmuna görə müqayisə edən ==, copy və komponentlərə ayırma imkanı yaradır.

Kotlin
data class User(val name: String, val age: Int)

fun main() {
    val u1 = User("Aysel", 15)
    val u2 = User("Aysel", 15)
    println(u1)
    println(u1 == u2)
    val older = u1.copy(age = 16)
    println(older)
    val (name, age) = older
    println("$name is $age")
}
Gözlənilən nəticə
User(name=Aysel, age=15)
true
User(name=Aysel, age=16)
Aysel is 16

object və companion obyekt

Bəzən proqramda bir şeyin yalnız bir nüsxəsi olmalıdır: tətbiqin parametrləri, verilənlər bazası ilə əlaqə. Bunun üçün class əvəzinə object yazılır — bu, həm sinfi təyin edir, həm də onun yeganə obyektini yaradır. Sinfin içindəki companion object isə obyekt yaratmadan, birbaşa sinfin adı ilə çağırılan funksiya və sabitlər üçündür, məsələn, obyekt yaradan «fabrik» funksiyaları üçün.

Kotlin
object Settings {
    var language = "az"
    fun describe() = "Language: $language"
}

class Temperature(val celsius: Double) {
    companion object {
        const val WATER_BOILS = 100.0
        fun fromFahrenheit(f: Double) = Temperature((f - 32) * 5 / 9)
    }
}

fun main() {
    println(Settings.describe())
    Settings.language = "en"
    println(Settings.describe())
    val t = Temperature.fromFahrenheit(212.0)
    println(t.celsius)
    println(t.celsius == Temperature.WATER_BOILS)
}
Gözlənilən nəticə
Language: az
Language: en
100.0
true

Varislik: open və override

Varislik mövcud sinif əsasında yeni sinif yaratmağa imkan verir: törəmə sinif valideyn sinfin xassə və metodlarını alır. Kotlin-də siniflər susmaya görə bağlıdır — onlardan törəmək üçün valideyn sinfə open yazmaq lazımdır. Törəmə sinfin dəyişə biləcəyi metod da open olmalıdır, törəmə sinifdə isə onun yeni versiyası override ilə yazılır. Valideyn iki nöqtədən sonra göstərilir: class Dog(name: String) : Animal(name).

Kotlin
open class Animal(val name: String) {
    open fun sound() = "..."
    fun introduce() = "$name says ${sound()}"
}

class Dog(name: String) : Animal(name) {
    override fun sound() = "Woof!"
}

class Cat(name: String) : Animal(name) {
    override fun sound() = "Meow!"
}

fun main() {
    val pets = listOf(Dog("Rex"), Cat("Mestan"), Animal("Nemo"))
    for (pet in pets) {
        println(pet.introduce())
    }
}
Gözlənilən nəticə
Rex says Woof!
Mestan says Meow!
Nemo says ...
Eyni introduce() hər obyektdə öz sound() versiyasını çağırır — buna polimorfizm deyilir.

İnterfeyslər

İnterfeys siniflərin nəyi bacarmalı olduğunu təsvir edən müqavilədir: onun xassə və metodlarını reallaşdıran hər sinif həmin interfeysin tipinə aid olur. İnterfeys metodun hazır versiyasını da saxlaya bilər. Sinif yalnız bir sinifdən törəyə bilər, amma istənilən sayda interfeysi reallaşdıra bilər.

Kotlin
interface Shape {
    val name: String
    fun area(): Double
    fun describe() = "$name: area ${area()}"
}

class Rectangle(val width: Double, val height: Double) : Shape {
    override val name = "Rectangle"
    override fun area() = width * height
}

class Circle(val radius: Double) : Shape {
    override val name = "Circle"
    override fun area() = 3.14 * radius * radius
}

fun main() {
    val shapes: List<Shape> = listOf(Rectangle(3.0, 4.0), Circle(2.0))
    shapes.forEach { println(it.describe()) }
    println(shapes.maxBy { it.area() }.name)
}
Gözlənilən nəticə
Rectangle: area 12.0
Circle: area 12.56
Circle
Sadəlik üçün π ≈ 3.14 götürülüb; dəqiq qiymət kotlin.math.PI-dədir.
YazılışNə vaxt işlətməli
classverilənləri və davranışı olan adi obyektlər
data classəsasən məlumat saxlayan obyektlər
objectyalnız bir nüsxəsi olan şey
open classtörəmə siniflər üçün baza
interfacebir neçə sinfin ortaq bacarığı (müqavilə)

Əsas fikirlər

  • class Student(val name: String) — əsas konstruktor xassəni birbaşa elan edir; obyekt new olmadan yaradılır.
  • data class avtomatik toString, məzmuna görə ==, copy və komponentlərə ayırma verir.
  • object yeganə nüsxə yaradır, companion object isə sinfin adı ilə çağırılan üzvləri saxlayır.
  • Siniflər və metodlar susmaya görə bağlıdır: varislik üçün open, yenidən təyin etmək üçün override lazımdır.
  • Sinif bir valideyn sinifdən törəyir, amma bir neçə interfeysi reallaşdıra bilər.

Özünü yoxla

10 sual. Hər düzgün cavab XP qazandırır.

1 / 10
data class Point(val x: Int, val y: Int) üçün println(Point(1, 2)) nə çap edir?