Extension property στην Kotlin — τι είναι, σύνταξη και εφαρμογή

Συγγραφέας: IT Sectr Δημοσιεύτηκε: 2026-06-21 Χρόνος ανάγνωσης: 8 λεπ

extension property — ένας μηχανισμός Kotlin που επιτρέπει την προσθήκη νέων ιδιοτήτων σε υφιστάμενες κλάσεις χωρίς κληρονομικότητα και χωρίς τροποποίηση του αρχικού κώδικα. Σε αντίθεση με τις extension functions, οι ιδιότητες-επεκτάσεις δεν μπορούν να αποθηκεύσουν κατάσταση — δηλώνονται μόνο με getter και προαιρετικά setter, επειδή δεν έχουν backing field. Σύμφωνα με Kotlin Documentation, 2025, τα extension properties μεταγλωττίζονται σε στατικές μεθόδους getter και setter με receiver ως πρώτη παράμετρο.

Βασικά σημεία

  • Extension property — ιδιότητα με receiver type, προσβάσιμη μέσω της σύνταξης ιδιοτήτων Kotlin
  • Δεν υπάρχει backing field — η extension property δεν μπορεί να αποθηκεύσει κατάσταση, μόνο να υπολογίσει
  • Getter είναι υποχρεωτικός, setter προαιρετικός — δηλώνονται όπως οι συνηθισμένες extension functions
  • Οι nullable τύποι υποστηρίζονται: receiver μπορεί να είναι nullable με εσωτερικό έλεγχο
  • Mutable extension property — μόνο κατά τη δήλωση var με getter και setter

Τι είναι το extension property στην Kotlin;

extension property — είναι μια συντακτική κατασκευή Kotlin που προσθέτει μια ιδιότητα σε έναν υφιστάμενο τύπο χωρίς να τροποποιεί τη δήλωσή του. Η ιδιότητα δηλώνεται με την προδιαγραφή του receiver-type και περιέχει υποχρεωτικά ένα getter. Η κλειδιή διαφορά από τις συνηθισμένες ιδιότητες — η απουσία backing field: η extension property δεν μπορεί να αποθηκεύσει δεδομένα, παρά μόνο να υπολογίζει βάσει του receiver-αντικειμένου.

Σύμφωνα με Kotlin Foundation Survey (2024), τα extension properties είναι λιγότερο δημοφιλή από τις extension functions — περίπου 45% των προγραματιστών τα χρησιμοποιεί τακτικά. Αυτό οφείλεται στον περιορισμό της έλλειψης κατάστασης, που στενεύει το πεδίο εφαρμογής. Παρόλα αυτά, για υπολογισμένες ιδιότητες που συνδέονται λογικά με τον τύπο, τα extension properties είναι η πιο σύντομη επιλογή.

Τα extension properties μεταγλωττίζονται σε ένα ζεύγος στατικών μεθόδων getter και setter. Σε επίπεδο bytecode, δεν υπάρχει διαφορά μεταξύ της κλήσης ενός extension property και μιας extension function — και τα δύο γίνονται στατικές μεθοδοι με παράμετρο receiver. Σύμφωνα με τα δεδομένα JetBrains (Kotlin Docs, 2025), η επιπλέον επιβάρυνση απουσιάζει πλήρως.

Χρησιμοποιείτε extension properties για σύντομες υπολογισμένες τιμές που πρέπει να φαίνονται ως ιδιότητες, όχι ως κλήσεις μεθόδων — αυτό βελτιώνει την αναγνωσιμότητα του κώδικα και ακολουθεί την αρχή της ομοιόμορφης πρόσβασης.

Σύνταξη extension property: val και var

Για τη δήλωση μιας extension property χρησιμοποιείται σύνταξη παρόμοια με μια συνηθισμένη ιδιότητα, αλλά με πρόθεμα receiver-type. val δηλώνει μια read-only extension property με υποχρεωτικό getter, var — mutable με getter και προαιρετικό setter.

kotlin
// Extension property μόνο για ανάγνωση
val String.isEmail: Boolean
    get() = this.contains("@") && this.contains(".")

// Κλήση
val valid = "test@test.com".isEmail

Παρατηρείστε: η extension property καλείται χωρίς παρενθέσεις — str.isEmail, όχι str.isEmail(). Αυτή είναι η κλειδιή διαφορά μεταξύ extension property και extension function: η property μοιάζει με πεδίο, αν και στην πραγματικότητα υπολογίζεται μέσω getter.

Generic extension property

Οι extension properties μπορούν να είναι γενικές — ο receiver μπορεί να χρησιμοποιεί generic παραμέτρους. Αυτό επιτρέπει τη δημιουργία καθολικών ιδιοτήτων που λειτουργούν με οποιονδήποτε τύπο συλλογής.

kotlin
val List<T>.secondOrNull: T?
    get() = if (size >= 2) this[1] else null

val items = listOf("a", "b", "c")
val second = items.secondOrNull // "b"

Η ιδιότητα secondOrNull λειτουργεί για οποιονδήποτε τύπο T, επιστρέφοντας το δεύτερο στοιχείο της λίστας ή null αν υπάρχουν λιγότερα από δύο στοιχεία. Αυτό είναι ένα τυπικό παράδειγμα όπου η extension property είναι πιο κατάλληλη από μια συνάρτηση — η πρόσβαση μοιάζει με ανάγνωση ενός πεδίου.

Γιατί η extension property δεν μπορεί να αποθηκεύσει κατάσταση

Η extension property δεν μπορεί να έχει backing field επειδή δεν προστίθεται στα μεταδεδομένα της κλάσης — υπάρχει μόνο ως ένα ζεύγος στατικών συναρτήσεων getter/setter. Backing field (η λέξη κλειδί field στην Kotlin) — είναι το εσωτερικό πεδίο της κλάσης που αποθηκεύει την τιμή της ιδιότητας. Η extension property δεν έχει πρόσβαση στην εσωτερική δομή της κλάσης.

kotlin
// ❌ ΣΦΑΛΜΑ: η extension property δεν μπορεί να έχει backing field
var String.cachedValue: String
    get() = "computed"
    set(value) {
        field = value // το πεδίο δεν είναι προσβάσιμο!
    }

// ✅ ΣΩΣΤΑ: χρησιμοποιείστε εξωτερική αποθήκευση
val cache = MutableMap<String, String>()

var String.cachedValue: String
    get() = cache[this] ?: ""
    set(value) { cache[this] = value }

Το εξωτερικό Map στο παράδειγμα λύνει το πρόβλημα αποθήκευσης, αλλά δημιουργεί ένα άλλο — διαρροή μνήμης. Οι τιμές που λαμβάνονται μέσω extension property ζουν στο Map για πάντα αν δεν καθαριστούν. Αυτός ο περιορισμός καθιστά τα extension properties ακατάλληλα για προσωρινή αποθήκευση η αποθήκευση προσωρινών δεδομένων.

Για προσωρινή αποθήκευση, συνιστάται η χρήση WeakHashMap ή μηχανισμών με αυτόματο καθάρισμα. Η JetBrains συνιστά να αποφεύγετε τη χρήση var extension properties με εξωτερική αποθήκευση σε κώδικα παραγωγής χωρίς προσεκτική διαχείριση κύκλου ζωής.

Extension property vs extension function: πότε τι να επιλέξω

Η επιλογή ανάμεσα σε extension property και extension function εξαρτάται από τη σημασιολογία: η ιδιότητα περιγράφει ένα χαρακτηριστικό του αντικειμένου, η συνάρτηση περιγράφει μια ενέργεια. Η αρχή της ομοιόμορφης πρόσβασης (Uniform Access Principle) λέει: ο πελάτης δεν πρέπει να γνωρίζει αν η τιμή υπολογίζεται ή αποθηκεύεται. Αν η τιμή μπορεί να παρουσιαστεί ως χαρακτηριστικό (μήκος, μέγεθος, κατάσταση) — χρησιμοποιείστε property.

ΚριτήριοExtension propertyExtension function
ΚλήσηΧωρίς παρενθέσεις: obj.propertyΜε παρενθέσεις: obj.function()
ΣημασιολογίαΧαρακτηριστικό, γνώρισμαΕνέργεια, λειτουργία
Backing fieldΔεν υποστηρίζεταιΔεν εφαρμόζεται
ΠαράμετροιΜόνο getter/setterΟποιεσδήποτε παράμετροι
ΑπόδοσηΊδια (στατική μέθοδος)Ίδια (στατική μέθοδος)
Παράδειγμαtext.lengthtext.isEmail()

Ο κανόνας είναι απλός: αν η λειτουργία δέχεται παραμέτρους — χρησιμοποιείστε extension function. Αν είναι μια απλή υπολογισμένη τιμή χωρίς παραμέτρους — extension property. Σύμφωνα με Android Architecture Guide (Google, 2025), προτίμηση πρέπει να δίνεται στις extension properties για πρόσβαση σε δεδομένα και στις extension functions για λειτουργίες με παρενέργειες.

Mutable extension property με var και setter

Η extension property με τη λέξη κλειδί var υποστηρίζει setter, αλλά χωρίς τη δυνατότητα αποθήκευσης της τιμής — ο setter συνήθως εκτελεί μια παρενέργεια ή αποθηκεύει δεδομένα σε εξωτερική αποθήκη. Η σύνταξη είναι ανάλογη με τις mutable ιδιότητες των κλάσεων.

kotlin
// Mutable extension property με setter
var StringBuilder.lastChar: Char
    get() = this[length - 1]
    set(value) {
        this.setCharAt(length - 1, value)
    }

val sb = StringBuilder("Kotlin")
println(sb.lastChar) // n
sb.lastChar = '!'
println(sb) // Kotli!

Η ιδιότητα lastChar — ένα κλασσικό παράδειγμα από την τεκμηρίωση Kotlin. Ο getter επιστρέφει τον τελευταίο χαρακτήρα του StringBuilder, ο setter τον αντικαθιστά με μια νέα τιμή. Παρατηρείστε: η κατάσταση αποθηκεύεται στον ίδιο τον StringBuilder (μέσω setCharAt), όχι σε ένα ξεχωριστό πεδίο — αυτή είναι σωστή χρήση της extension property.

Πρακτικά παραδείγματα extension properties

Σε πραγματικά έργα, τα extension properties χρησιμοποιούνται συχνότερα για απλοποίηση της πρόσβασης σε δεδομένα συλλογών, υπολογισμό μεγεθών ή καταστάσεων στοιχείων UI και δημιουργία βολικής API πάνω σε υφιστάμενες κλάσεις. Η τυπική βιβλιοθήκη Kotlin χρησιμοποιεί ενεργά αυτόν τον μηχανισμό: size, indices, lastIndex για συλλογές — αυτά είναι extension properties.

kotlin
// Extension properties για συλλογές
val List<Int>.sumFast: Int
    get() = fold(0) { acc, i -> acc + i }

val String.half: String
    get() = this.substring(0, length / 2)

// Extension property για Android View
val View.isVisible: Boolean
    get() = visibility == View.VISIBLE

// Έλεγχος null μέσω ασφαλού receiver
val String?.isNullOrBlank: Boolean
    get() = this == null || this.isBlank()

Η extension property isVisible για View — ένα παράδειγμα που κάθε προγραματιστής Android πρέπει να γνωρίζει. Αντί για view.visibility == View.VISIBLE μπορείτε να γράψετε view.isVisible. Δεν είναι μόνο πιο σύντομο, αλλά διαβάζεται σαν φυσική γλώσσα: “αν η προβολή είναι ορατή”. Παρά την απλότητα, τέτοιες ιδιότητες βελτιώνουν σημαντικά την αναγνωσιμότητα του κώδικα.

Συχνές ερωτήσεις

Μπορώ να δηλώσω extension property για companion object;

Όχι, τα extension properties δεν μπορούν να δηλωθούν για companion object ή object declaration. Ο μηχανισμός extension εφαρμόζεται μόνο σε κλάσεις, διεπαφές και nullable τύπους. Για object χρησιμοποιείστε συνηθισμένες συναρτήσεις κορυφαίου επιπέδου.

Σε τι διαφέρει η extension property από την inline ιδιότητα;

Η inline ιδιότητα (με τον τροποποιητή inline) — είναι ένας μηχανισμός Kotlin για την κλήση getter/setter χωρίς δημιουργία αντικειμένου-ιδιότητας. Extension property μεταγλώσσεται πάντα σε στατική μέθοδο, ενώ η inline ιδιότητα μεταγλώσσεται σε κλήση χωρίς περιτύλιγμα. Λύνουν διαφορετικά προβλήματα: η extension property προσθέτει ιδιότητα σε έναν υφιστάμενο τύπο, η inline βελτιστοποιεί τις κλήσεις των δικών της ιδιοτήτων.

Υποστηρίζει η extension property σχολιασμούς;

Ναι, η extension property μπορεί να περιέχει σχόλια, αλλά μόνο σε επίπεδο δήλωσης. Δεν μπορείτε να σχολιάσετε ξεχωριστά το getter ή setter μιας extension property — σε αντίθεση με τις συνηθισμένες ιδιότητες κλάσης. Παράδειγμα: @JvmName(“getIsValid”) val String.isValid get() = true.

Μπορώ να χρησιμοποιήσω extension property με companion object της κλάσης;

Όχι, τα extension properties δεν μπορούν να δηλωθούν με companion object ως receiver. Αυτός είναι ένας περιορισμός της γλώσσας — η extension property λειτουργεί μόνο με πρατότυπα τυπών, και το companion object είναι στατικό περιεχόμενο. Χρησιμοποιείστε extension functions κορυφαίου επιπέδου ή σταθερές.

Επηρεάζει η extension property το μέγεθος APK;

Ελάχιστα. Κάθε extension property προσθέτει μία στατική μέθοδο getter (και προαιρετικά setter) στο μεταγλωττισμένο bytecode. Για σύγκριση: η δημιουργία μιας κλάσης-περιτύλιγματος με την ίδια ιδιότητα προσθέτει ολόκληρη την κλάση. Τα extension properties — ελαφρύτερη προσέγγιση για επέκταση λειτουργικότητας.

Περίληψη

  • Extension property — υπολογισμένη ιδιότητα για υφιστάμενο τύπο χωρίς κληρονομικότητα
  • Δεν υπάρχει backing field — η κατάσταση δεν αποθηκεύεται, μόνο υπολογίζεται μέσω getter
  • var με setter — δυνατόν, αλλά απαιτεί εξωτερική αποθήκευση για εγγραφή δεδομένων
  • Σύνταξη — val/var με receiver-type και υποχρεωτικό getter
  • Απόδοση — μηδενικό overhead, μεταγλώσσεται σε στατική μέθοδο
  • Εφαρμογή — υπολογισμένα χαρακτηριστικά: μήκος, κατάσταση, μέγεθος, έλεγχοι
  • Περιορισμός — δεν είναι κατάλληλη για αποθήκευση κατάστασης, cache χωρίς διαχείριση μνήμης

Θα αναπτύξουμε μια εφαρμογή για κινητά έτοιμη για χρήση

Η IT Sectr δημιουργεί εφαρμογές iOS και Android για νεοφυείς επιχειρήσεις και επιχειρήσεις από το 2017. Θα σας συμβουλεύσουμε και θα προτείνουμε την καλύτερη λύση.

Συζήτηση έργου

Διαβάστε επίσης