Classi in linea a Kotlin

1. Panoramica

In Kotlin 1.3+, abbiamo un nuovo tipo di classe sperimentale, chiamato classe inline. In questo tutorial, ci concentreremo sull'uso delle classi inline e anche su alcuni dei loro limiti.

2. Configurazione

Come accennato prima, le classi inline sono una caratteristica sperimentale di Kotlin. Di conseguenza, il compilatore lancerà un avviso che indica lo stato sperimentale della funzionalità.

Per evitare questo avviso, possiamo aggiungere la seguente opzione del compilatore Maven alla nostra configurazione:

  -XXLanguage:+InlineClasses  

3. Cosa sono le classi in linea?

Le classi inline ci forniscono un modo per racchiudere un tipo, aggiungendo così funzionalità e creando un nuovo tipo da solo.

A differenza dei normali wrapper (non inline), beneficeranno di prestazioni migliorate. Ciò accade perché i dati vengono inseriti nei relativi utilizzi e la creazione di istanze degli oggetti viene ignorata nel codice compilato risultante.

Vediamo un esempio di una classe inline chiamata InlinedCircleRadius con una proprietà di tipo Double che rappresenta il raggio:

val circleRadius = InlinedCircleRadius(5.5)

Per la JVM, il nostro codice è in realtà solo:

val circleRadius = 5.5

Si noti come il nostro InlinedCircleRadius non sia istanziato nel codice compilato perché il valore sottostante è inline, sollevandoci dalle penalità sulle prestazioni associate all'istanziazione.

3.1. Esempio di utilizzo

Ora che sappiamo cosa sono le classi inline, discuteremo del loro utilizzo.

Una singola proprietà inizializzata nel costruttore principale è il requisito di base di una classe inline . La singola proprietà rappresenterà l'istanza della classe in fase di esecuzione.

Pertanto, per avere una definizione corretta, possiamo utilizzare una sola riga di codice:

inline class InlineDoubleWrapper(val doubleValue : Double)

Abbiamo definito InlineDoubleWrapper come un semplice wrapper su un oggetto Double e vi abbiamo applicato la parola chiave inline . Infine, ora possiamo utilizzare questa classe nel nostro codice senza ulteriori modifiche:

@Test fun whenInclineClassIsUsed_ThenPropertyIsReadCorrectly() { val piDoubleValue = InlineDoubleWrapper(3.14) assertEquals(3.14, piDoubleValue.doubleValue) }

4. Membri della classe

Fino ad ora, abbiamo utilizzato classi inline proprio come semplici wrapper. Ma sono molto di più. Ci permettono anche di definire proprietà e funzioni proprio come le classi normali. Il prossimo esempio definisce una proprietà che rappresenta il diametro e una funzione per restituire l'area del cerchio:

inline class CircleRadius(private val circleRadius : Double) { val diameterOfCircle get() = 2 * circleRadius fun areaOfCircle = 3.14 * circleRadius * circleRadius }

Creeremo ora un test per la nostra proprietà DiameterOfCircle . Istanzerà la nostra classe inline CircleRadius e quindi chiamerà la proprietà:

@Test fun givenRadius_ThenDiameterIsCorrectlyCalculated() { val radius = CircleRadius(5.0) assertEquals(10.0, radius.diameterOfCircle) }

Ed ecco un semplice test per la funzione areaOfCircle :

@Test fun givenRadius_ThenAreaIsCorrectlyCalculated() { val radius = CircleRadius(5.0) assertEquals(78.5, radius.areaOfCircle()) }

Tuttavia, ci sono alcune limitazioni su ciò che possiamo e non possiamo definire all'interno delle nostre classi inline. Sebbene proprietà e funzioni siano consentite, dobbiamo menzionare che i blocchi di inizializzazione , le classi interne e i campi di supporto non lo sono.

5. Eredità

È importante ricordare che le classi inline possono ereditare solo dalle interfacce e, poiché non possiamo avere sottoclassi, anche le classi inline sono effettivamente finali.

Data un'interfaccia Drawable con un metodo draw () , implementeremo questo metodo nella nostra classe CircleRadius :

interface Drawable { fun draw() } inline class CircleRadius(private val circleRadius : Double) : Drawable { val diameterOfCircle get() = 2 * circleRadius fun areaOfCircle() = 3.14 * circleRadius * circleRadius override fun draw() { println("Draw my circle") } }

6. Conclusioni

In questo breve articolo, abbiamo esplorato le classi in linea in Kotlin. Inoltre, abbiamo parlato di ereditarietà e definizione di proprietà e funzioni.

Come al solito, tutti questi esempi e frammenti possono essere trovati su GitHub.