Kotlin: Klassen
Willemers Informatik-Ecke
  • Funktionen
  • Vererbung

  • Eine Klasse fasst mehrere Variablen zusammen und fügt passende Funktionen hinzu. Auf diese Weise entsteht ein selbstgebastelter Typ. Von diesem Typ können eigene Variablen erzeugt werden, die man als Instanzen oder Objekte bezeichnet. Die Klassenvariablen der Objekte bezeichnet man in der objektorientierten Programmierung als Attribute und die Klassenfunktionen als Methoden.

    Klasse Bruch

    Als Beispiel erstellen wir die Klasse Bruch. Als Attribute hat sie einen Zähler namens zaehler und einen Nenner namens nenner. Brüche werden anders behandelt als gewöhnliche Zahlen. Darum wird die Klasse über kurz oder lang Methoden bereitstellen, um mit Brüchen rechnern zu können.
    class Bruch {
        var zaehler = 0
        var nenner  = 1
    }
    
    Eine Variable der Klasse Bruch entsteht durch Zuweisung des Klassennamens gefolgt von Klammern. Konkret bedeuten die Klammern den Aufruf des Konstruktors. Anschließend kann über das Objekt das Attribut gesetzt und gelesen werden.
    var bruch = Bruch()
    bruch.zaehler = 1
    bruch.nenner  = 2
    

    Konstruktoren

    Der Konstruktor einer Klasse ist eine Methode, die automatisch bei der Erstellung des Objekts aufgerufen wird und genutzt werden kann, um die Attribute des Objekts zu initialisieren.

    Primärer Konstruktor

    Die Initialisierung erfolgt in dem Block, der mit dem Schlüsselwort init eingeleitet wird. Dieser Block kann beispielsweise dafür sorgen, dass die Attribute initialisiert werden.
    class Bruch {
        var zaehler : Int
        var nenner  : Int
        init {
            zaehler = 0
            nenner  = 1
        }
    }
    

    Konstruktorparameter

    Soll der Konstruktor Parameter erhalten, kann an den Klassennamen ein Klammerpaar mit den Parametern definiert werden. Anschließend müssen diese Parameter beim Anlegen belegt werden.
    class Bruch(zaehler: Int, nenner: Int) {
        var zaehler: Int = zaehler
        var nenner: Int = nenner
    
    Eine Kurzform kann erzielt werden, indem den Parametern das Schlüsselwort var vorangestellt wird.
    class Bruch (var zaehler : Int, var nenner : Int) {
    }
    
    Sind solche Parameter gesetzt, müssen die Parameter bei Anlegen eines Objekts bedient werden. Das folgende Objekt wird mit 2/3 vorbesetzt:
    var bruch = Bruch(2,3)
    

    Sekundärer Konstruktor

    Der sekundäre Konstruktor verwendet das Schlüsselwort constructor als Funktionsnamen für sekundäre Konstruktoren. Er wird vor allem dann benötigt, wenn mehrere Konstruktoren mit unterschiedlichen Parametern benötigt werden.
    class Brach (_zaehler:Int, _nenner:Int){
        var zaehler : Int = _zaehler
        var nenner  : Int = _nenner
        init {
            zaehler = 0
            nenner  = 1
        }
        constructor (z:Int) : this(z, 1) {
        }
    }
    
    Nun können beide Konstruktoren verwendet werden.
    var b1 = Bruch(2,3)
    var b2 = Bruch(2)
    

    Klasse Bruch mit Operatoren

    Das folgende Beipiel umfasst die Klasse Bruch. Ein Bruch-Objekt muss bei seiner Erzeugung mit Zähler und Nenner besetzt werden. Die Initialisierung sorgt dafür, dass der Euklid den größten gemeinsamen Teiler berechnet und Zähler und Nenner dadurch teilt. Auf diese Weise sind die Brüche immer optimal gekürzt.

    Die Operatoren * und + werden überladen. So können Brüche also wie normale Zahlenwerte multipliziert und addiert werden.

    class Bruch(_zaehler: Int, _nenner: Int) {
        private var zaehler: Int = _zaehler
        private var nenner: Int  = _nenner
    
        init {
            var ggt = euklid(zaehler, nenner)
            this.zaehler = zaehler/ggt
            this.nenner  = nenner/ggt
        }
    
        private fun euklid(pa :Int, pb :Int) :Int {
            var a = pa // Übernahme der Parameter
            var b = pb // Übernahme der Parameter
            while (b!=0) {
                var parken = a % b;
                a = b;
                b = parken;
            }
            return a;
        }
    
        // Operator + wird überladen    
        operator fun plus(other: Bruch): Bruch {
            return Bruch(zaehler * other.nenner + other.zaehler * nenner,
                         nenner * other.nenner)
        }
    
        // Operator * wird überladen - Kurzform
        operator fun times(other: Bruch) = Bruch(zaehler * other.zaehler,
                                                 nenner * other.nenner)
    
        override fun toString(): String {
            return "$zaehler/$nenner"
        }
    }
    
    fun main() {
        var bruch = Bruch(2, 3)
        var operand = Bruch(1, 2)
        var produkt = bruch * operand
        println(produkt)
        var summe = bruch + operand
        println(summe)
    }
    

    Data Class

    Eine Datenklasse dient zur Verarbeitung selbstdefinierter, zusammengesetzter Typen.
    data class Name (var name: String, var alter: Int)
    
    Dabei werden Getter und Setter, equals und toString automatisch generiert.

    Singleton: object

    object myObject {
        var zahl = 0
        fun zaehle(a: Int) {
            zahl++
        }
        fun hole() : Int {
            return zahl
        }
    }