Menu
Coddy logo textTech

Deklarowanie interfejsów

Część sekcji Programowanie obiektowe ścieżki Kotlin w Coddy. Lekcja 22 z 57.

Interfejs określa, co może robić dany typ, nie mówiąc, jak to robi. Deklaruje metody i właściwości, które musi udostępniać każda implementująca go klasa. Klasa implementuje interfejs za pomocą dwukropka, tak jak w przypadku nadklasy, ale bez nawiasów, ponieważ interfejs nie ma konstruktora:

interface Drawable {
    fun draw(): String
}
class Circle(val radius: Int) : Drawable {
    override fun draw() = "circle with radius $radius"
}
class Line(val length: Int) : Drawable {
    override fun draw() = "-".repeat(length)
}

Wewnątrz main:

println(Circle(3).draw())
println(Line(5).draw())

Wynik:

circle with radius 3
-----

Interfejs może również deklarować właściwości. Klasa udostępnia je jako właściwości konstruktora, przechowywane właściwości lub gettery; sam interfejs niczego nie przechowuje:

interface Vehicle {
    val wheels: Int
    val label: String
}
class Car(override val label: String) : Vehicle {
    override val wheels = 4
}
class Bike : Vehicle {
    override val wheels = 2
    override val label: String
        get() = "bike on $wheels wheels"
}

Wewnątrz main:

println("${Car("taxi").label}: ${Car("taxi").wheels}")
println(Bike().label)

Wynik:

taxi: 4
bike on 2 wheels

Każdy element zadeklarowany w interfejsie musi zostać zaimplementowany z użyciem override, w przeciwnym razie klasa się nie skompiluje. Nie można utworzyć instancji interfejsu:

interface Speaker {
    fun speak(): String
    val volume: Int
}
// class Mute : Speaker { override fun speak() = "" }   // błąd: volume nie jest zaimplementowane
// class Loud : Speaker() { ... }                      // błąd: interfejs nie ma konstruktora
// val s = Speaker()                                   // błąd: nie można utworzyć instancji interfejsu

Interfejs i klasa abstrakcyjna deklarują elementy bez treści. Interfejs nie ma konstruktora ani przechowywanego stanu, a klasa może implementować wiele interfejsów, ale rozszerzać tylko jedną klasę. Użyj interfejsu dla możliwości wspólnej dla niezwiązanych ze sobą klas, takiej jak Drawable lub Comparable, a klasy abstrakcyjnej jako wspólnej klasy bazowej ze stanem.

interface Drawable { fun draw(): String }                   // pewna zdolność
abstract class Shape(val name: String) { abstract fun area(): Double }   // klasa bazowa ze stanem
class Square(val s: Double) : Shape("square"), Drawable {  // jedna klasa, dowolna liczba interfejsów
    override fun area() = s * s
    override fun draw() = "[]"
}
challenge icon

Wyzwanie

Łatwy

Zadeklaruj składowe interfejsu Shape: właściwość tylko do odczytu name oraz metody area() i perimeter(), obie zwracające Double. Zaimplementuj je w klasach Rectangle(width, height) (nazwa rectangle) i Circle(radius) (nazwa circle, używającej Math.PI). Następnie dokończ funkcję describe(shape), która zwraca rectangle: area 12.00, perimeter 14.00 z dwoma miejscami po przecinku, korzystając wyłącznie ze składowych interfejsu Shape.

Dostarczony kod odczytuje wiersze r,3,4 lub c,2, tworzy odpowiedni kształt i wyświetla describe(shape).

Umieść swój kod w plikach Shape.kt, Rectangle.kt, Circle.kt i Functions.kt. Plik Main.kt zawiera dostarczony kod wejścia/wyjścia i nie można go edytować.

Spróbuj swoich sił

fun main() {
    // Dostarczony kod wejścia/wyjścia: pozostaw go bez zmian
    val input = generateSequence(::readLine).toList()
    for (line in input) {
        val p = line.split(",").map { it.trim() }
        val shape: Shape = if (p[0] == "r") Rectangle(p[1].toDouble(), p[2].toDouble()) else Circle(p[1].toDouble())
        println(describe(shape))
    }
}
quiz iconSprawdź się

Ta lekcja zawiera krótki quiz. Zacznij lekcję, żeby na niego odpowiedzieć i śledzić swoje postępy.

Wszystkie lekcje w sekcji Programowanie obiektowe

Poćwicz samodzielnie: Edytor online Kotlin