Nessun risultato. Prova con un altro termine.
Guide
Notizie
Software
Tutorial

Programmazione Orientata agli Oggetti

Anche Kotlin supporta i costrutti principali della programmazione orientata agli oggetti: ecco come creare classi, oggetti, costruttori, getter e setter.
Anche Kotlin supporta i costrutti principali della programmazione orientata agli oggetti: ecco come creare classi, oggetti, costruttori, getter e setter.
Link copiato negli appunti

In Kotlin, possiamo applicare tutti i paradigmi tradizionali della programmazione orientata agli oggetti con una serie di innovazioni che lo rendono un linguaggio estremamente moderno.
Per creare una classe in Kotlin, si utilizza la parola chiave class. Quella che vediamo nel seguente snippet è già una definizione valida, sebbene sia vuota:

class Libro

Nonostante non contenga proprietà né metodi, essa potrebbe già essere utilizzata come tipo di dato:

var testo:Libro

La seguente definizione arricchisce la classe di due variabili d'istanza che rappresentano il nome dell'autore
ed il titolo dell'opera:

class Libro(titoloLibro:String, autoreLibro:String){
    var titolo=titoloLibro
    var autore=autoreLibro
}

Abbiamo usato la parola chiave var perché intendiamo dare la possibilità di cambiare i valori delle variabili dopo
l'inizializzazione, ma avremmo anche potuto usare val per creare delle proprietà read-only, a sola lettura.

Si noti che, subito dopo la definizione class Libro, vengono dichiarate alcune
variabili, (nominativo:String, numeroConto:String): quello è il modo in cui si indica un costruttore
in Kotlin. Le variabili in esso nominate vengono direttamente utilizzate per l'inizializzazione delle
variabili di istanza, e ciò soddisfa una delle principali incombenze dei costruttori. Istanziando un oggetto
nel metodo main, potremo già vederlo al lavoro:

fun main(args:Array) {
    var libro=Libro("Coltivare un orto in casa","Andrea Rossi")
	println("\"${libro.titolo}\" scritto da ${libro.autore}")
}

L'output sarà infatti il seguente:

"Coltivare un orto in casa" scritto da Andrea Rossi

Il limite di questo tipo di costruttore è rappresentato dall'impossibilità di far intervenire del
codice durante l'assegnazione dei valori, ma può essere risolto con un blocco init che interviene
in fase di inizializzazione:

class Libro(titoloLibro:String, autoreLibro:String){
	// OMISSIS: variabili d'istanza
	init{
        println("Inizializzo il libro \"$titolo\"")
    }
}

Si noti che all'interno di init abbiamo potuto utilizzare il valore della variabile
titolo in quanto le proprietà risultano già assegnate.

Costruttori secondari

Per operare l'overloading sui costruttori (più costruttori con argomenti diversi) si ricorre alla parola
chiave constructor. Nel seguente esempio, definiamo il costruttore primario come visto nel paragrafo precedente,
ma offrendogli un unico parametro, il titolo del libro, mentre nel costruttore secondario permettiamo di impostare anche il nome dell'autore.
Ciò darà la possibilità di creare un testo con autore anonimo (cosa non impossibile nell'editoria) ed includeremo un metodo
per poter verificare questa evenienza: un metodo in Kotlin non è altro che una funzione innestata in una classe che potrà
lavorare sulle variabili d'istanza.

class Libro(titoloLibro:String){
    var titolo=titoloLibro
    var autore:String?=null
    constructor(titoloLibro:String, autoreLibro: String): this(titoloLibro)
    {
        autore=autoreLibro
    }
    init{
        println("Inizializzo il libro \"$titolo\"")
    }
    fun autoreAnonimo():Boolean
    {
        return autore==null
    }
}

Si noti che a differenza della funzione main, il metodo autoreAnonimo
restituisce un risultato il cui tipo, Boolean, viene indicato alla fine della definizione.

Con le seguenti righe potremo provare contemporaneamente sia il costruttore secondario sia il metodo
autoreAnonimo:

var testo=Libro("Favole antiche")
if (testo.autoreAnonimo())
   println("Di \"${testo.titolo}\" non si conosce l'autore")
else
   println("Di \"${testo.titolo}\" si conosce l'autore")

ottenendo in output:

Di "Favole antiche" non si conosce l'autore

Tale approccio funziona ed è in linea con i principi su cui si fonda la programmazione orientata agli oggetti classica. Vedremo nel prossimo paragrafo e nelle lezioni successive
che in Kotlin esistono diverse alternative all'impiego di metodi di questo genere.

Getter e setter

Si possono dotare le proprietà anche di getter e setter, ma di una forma così snella da essere meno invasivi dei classici metodi. Questa la loro
forma in generale:

var nomeVariabile   // seguito da tipo di dato e inizializzazione
get(){
	// codice del getter
}
set(value){
	// assegniamo value al campo
}

I getter verranno invocati ogni volta che si accederà in lettura ad una variabile d'istanza, mentre i setter ogni volta che si tenterà di
assegnare un valore. A proposito della classe Libro costruita poco fa, possiamo immaginare una proprietà numeroPagine che memorizza il numero
di pagine del testo ma che accetta valori solo se maggiori di 0. Si potrebbe dotarla di questo setter:

var numeroPagine: Int=0
set(v){
       if (v>0)
	      field=v
       else
          println("Errore: numero di pagine non maggiore di zero")
}

All'interno del setter ci riferiamo al campo in questione con la parola chiave field. In questo caso
aggiungiamo anche la stampa di un messaggio in caso di errore anche se a puro scopo di debug.

Potrebbe essere applicato al campo autore un getter che restituirebbe la stringa "Anonimo" nel caso in cui la variabile
d'istanza autore contenesse null. Si tenga presente che così facendo perderebbe significato il metodo autoreAnonimo creato poco fa,
ma quest'ultimo approccio è più in linea con le prassi del linguaggio Kotlin:

var autore:String?=null
get(){
    return if (field!=null) field else "Anonimo"
}

Esempio conclusivo

Riepilogando, con gli elementi incontrati sinora potremmo definire una classe in grado di produrre i funzionamenti necessari rivolgendosi meno al
classico approccio che separava nettamente variabili d'istanza e metodi a favore di una nuova sintassi che preferisce fornire variabili dal valore assegnato e proprietà
gestite dinamicamente con getter e setter:

class Libro(titolo:String){
    var titolo=titolo
    var autore:String?=null
        get(){
            return if (field!=null) field else "Anonimo"
        }
    constructor(titoloLibro:String, autoreLibro: String): this(titoloLibro)
    {
        autore=autoreLibro
    }
    var numeroPagine: Int=0
        set(v){
            if (v>0) field=v
            else
                println("Errore: numero di pagine non maggiore di zero")
        }
    var descrizione:String?=null
        get(){
            return "\"${titolo}\" scritto da $autore"
        }
    init{
        println("Inizializzo il libro \"$titolo\"")
    }
}

Il main per sperimentare il codice precedente potrebbe essere il seguente:

fun main(args:Array) {
    var testo=Libro("Sfornare dolci", "Giacomo Bianchi")
    testo.numeroPagine=120
    println("${testo.descrizione} di ${testo.numeroPagine} pagine")
}

Ti consigliamo anche