Classes abstraites
Fait partie de la section Programmation orientée objet du Journey Kotlin de Coddy. Leçon 20 sur 57.
Une classe abstract est une superclasse qui ne peut pas être instanciée seule. Elle peut déclarer des membres abstract sans corps, et chaque sous-classe concrète doit les implémenter :
abstract class Shape(val name: String) {
abstract fun area(): Double
fun describe() = "$name with area ${area()}"
}
class Circle(val r: Double) : Shape("circle") {
override fun area() = 3.14 * r * r
}
class Rect(val w: Double, val h: Double) : Shape("rect") {
override fun area() = w * h
}À l'intérieur de main :
val shapes: List<Shape> = listOf(Circle(1.0), Rect(2.0, 3.0))
for (s in shapes) println(s.describe())Sortie :
circle with area 3.14
rect with area 6.0Une classe abstraite est ouverte sans le mot-clé, et ses membres abstraits le sont également, de sorte que les sous-classes n’écrivent que override. La création de la classe abstraite elle-même ne compile pas, et une sous-classe qui omet un membre abstrait doit également être abstraite. Utilisez une classe abstraite lorsque la superclasse n’a pas de comportement pertinent qui lui soit propre pour certains membres :
// val s = Shape("blob") // erreur : impossible de créer une instance d'une classe abstraite
// class Blob : Shape("blob") // erreur : Blob n'implémente pas area()
abstract class Polygon(name: String) : Shape(name) // bien : toujours abstraitUne classe abstraite peut avoir un constructeur, un état et des méthodes normales, que les sous-classes héritent. Un usage courant est une procédure fixe dont les étapes varient, la méthode modèle : la méthode de la superclasse exécute les étapes, et les sous-classes remplissent celles qui sont abstraites :
abstract class Report(val title: String) {
fun render() = "== $title ==\n${body()}\n(${footer()})"
abstract fun body(): String
open fun footer() = "end"
}
class Sales(val total: Int) : Report("Sales") {
override fun body() = "total: $total"
}
class Stock(val items: Int) : Report("Stock") {
override fun body() = "items: $items"
override fun footer() = "counted today"
}Dans main :
println(Sales(420).render())
println(Stock(17).render())Sortie :
== Sales ==
total: 420
(end)
== Stock ==
items: 17
(counted today)Les propriétés abstraites fonctionnent de la même manière. La sous-classe fournit la valeur en tant que propriété de constructeur, propriété stockée ou accesseur :
abstract class Worker(val name: String) {
abstract val monthly: Int
fun yearly() = monthly * 12
}
class Salaried(name: String, override val monthly: Int) : Worker(name)
class Hourly(name: String, val hours: Int, val rate: Int) : Worker(name) {
override val monthly: Int
get() = hours * rate
}Dans main :
val staff = listOf(Salaried("Ada", 4000), Hourly("Bo", 80, 25))
for (w in staff) println("${w.name}: ${w.yearly()}")Sortie :
Ada: 48000
Bo: 24000Défi
FacileDiscount est une classe abstraite. Elle déclare la méthode abstraite amount(price) et implémente apply(price), qui renvoie le prix moins amount(price), sans jamais descendre en dessous de 0. Complétez les sous-classes : PercentOff(percent) prend ce pourcentage du prix (arrondi à l’entier inférieur), FixedOff(value) prend une valeur fixe, et SpendMore(threshold, off) prend off uniquement lorsque le prix est supérieur ou égal à threshold.
Le code fourni lit le prix, puis applique les remises p,10, f,300 ou s,500,50, applique chacune au prix et affiche 1000 -> 900.
Votre code doit se trouver dans Discount.kt, PercentOff.kt, FixedOff.kt et SpendMore.kt. Main.kt contient le code fourni pour les entrées et les sorties et ne peut pas être modifié.
Essayez vous-même
fun main() {
// Code d'entrée/sortie fourni : le laisser tel quel
val input = generateSequence(::readLine).toList()
val price = input[0].toInt()
for (line in input.drop(1)) {
val p = line.split(",")
val discount: Discount = when (p[0]) {
"p" -> PercentOff(p[1].toInt())
"f" -> FixedOff(p[1].toInt())
else -> SpendMore(p[1].toInt(), p[2].toInt())
}
println("$price -> ${discount.apply(price)}")
}
}
Cette leçon comprend un petit quiz. Commencez la leçon pour y répondre et suivre votre progression.
Toutes les leçons de Programmation orientée objet
1Classes et objets
Travailler avec des fichiersDéfinir des classesConstructeurs primairesBlocs init et validationConstructeurs secondairesRécapitulatif - Carte de bibliothèque4Héritage
Classes ouvertes et sous-classesRedéfinition des membressuper et constructeursClasses abstraitesRécapitulatif – Annuaire du personnel2Propriétés et encapsulation
Accesseurs personnalisésModificateurs de visibilitéSetters privéslazy et lateinitRécapitulatif - Compte bancaire5Interfaces
Déclarer des interfacesMéthodes par défautInterfaces multiplesInterfaces en tant que typesRécapitulatif - Méthodes de paiement8Génériques
Fonctions génériquesClasses génériquesContraintes de typeVariance avec in et outRécapitulatif - File de priorité11Projet : Gestion de bibliothèque
Livres et membresEmprunter des livresEntraînez-vous par vous-même : Playground Kotlin