Struct — είναι ένας τύπος-τιμής (value type) στη γλώσσα Swift, του οποίου τα στιγμιότυπα αντιγράφονται κατά τη μεταφορά μεταξύ τμημάτων κώδικα. Σε αντίθεση με τις κλάσεις, οι δομές δεν υποστηρίζουν κληρονομικότητα, αλλά υλοποιούν πρωτόκολλα, περιέχουν ιδιότητες και μεθόδους και παρέχουν προβλέψιμη διαχείριση μνήμης χωρίς ARC. Σύμφωνα με τον Swift Programming Language Guide, 2026, το struct είναι το βασικό δομικό στοιχείο της Swift — ακόμα και οι τυπικοί τύποι Int, String, Array και Dictionary υλοποιούνται ως δομές. Η γλώσσα συνιστά τις δομές ως προτιμώμενη επιλογή για τη μοντελοποίηση δεδομένων.
Κύρια σημεία
Struct (δομή) — είναι ένας σύνθετος τύπος δεδομένων στη Swift που ομαδοποιεί σχετικές ιδιότητες και μεθόδους σε μια ενιαία οντότητα. Σε αντίθεση με τις κλάσεις, οι δομές είναι value types: κατά τη μεταβίβαση σε μια συνάρτηση ή την ανάθεση σε μια νέα μεταβλητή, δημιουργείται ένα ανεξάρτητο αντίγραφο της δομής, όχι μια αναφορά στο αρχικό αντικείμενο.
Η Swift χρησιμοποιεί δομές για όλους τους πρωτόγονους τύπους: Int, Double, String, Bool, Array, Dictionary και Set. Αυτό σημαίνει ότι ακόμα και ο βασικός αριθμός Int συμπεριφέρεται ως δομή — κατά την ανάθεση δημιουργείται αντίγραφο. Ο προγραμματιστής μπορεί να ορίσει τη δική του δομή με αυθαίρετο σύνολο ιδιοτήτων και μεθόδων.
Σύμφωνα με το Swift Evolution (SE-0143), η απόφαση να υλοποιηθούν οι τυπικοί τύποι ως δομές οφείλεται στην απόδοση και την προβλεψιμότητα. Τα value types δεν δημιουργούν κύκλους αναφοράς, δεν απαιτούν μέτρηση αναφορών ARC και εγγυώνται ότι η αλλαγή του αντιγράφου δεν θα επηρεάσει το πρωτότυπο — αυτό είναι κρίσιμο για την αμεταβλητότητα δεδομένων σε πολυνηματικά σενάρια.
Value type semantics — η βασική διαφορά μεταξύ struct και class. Όταν αναθέτετε μια δομή σε μια νέα μεταβλητή ή τη μεταβιβάζετε σε μια συνάρτηση, η Swift δημιουργεί ένα ανεξάρτητο αντίγραφο όλων των δεδομένων. Οποιεσδήποτε αλλαγές στο αντίγραφο δεν επηρεάζουν το πρωτότυπο, εξαλείφοντας τις παρενέργειες που χαρακτηρίζουν τους τύπους αναφοράς.
// Παράδειγμα σημασιολογίας value type
struct Point {
var x: Double
var y: Double
}
var p1 = Point(x: 10, y: 20)
var p2 = p1 // Το p2 είναι ένα ανεξάρτητο αντίγραφο του p1
p2.x = 99 // Μόνο το p2 αλλάζει
print(p1.x) // 10 — το p1 παραμένει αμετάβλητο
print(p2.x) // 99
Η Swift χρησιμοποιεί Copy-on-Write (COW) για βελτιστοποίηση της αντιγραφής. Εάν πολλές μεταβλητές αναφέρονται στην ίδια δομή, αλλά καμία δεν τροποποιεί τα δεδομένα, δεν πραγματοποιείται πραγματική αντιγραφή. Η Swift μοιράζεται τη μνήμη μεταξύ των μεταβλητών μέχρι την πρώτη μετάλλαξη — τότε δημιουργείται ένα πραγματικό αντίγραφο. Αυτό αποτρέπει περιττές λειτουργίες εκχώρησης και επιταχύνει την εργασία με συλλογές.
Από προεπιλογή, οι μέθοδοι μιας δομής δεν μπορούν να τροποποιήσουν τις ιδιότητές της — η Swift απαιτεί ρητή ένδειξη mutating για μεθόδους που κάνουν αλλαγές. Αυτός ο περιορισμός προστατεύει από τυχαία μετάλλαξη και καθιστά τον κώδικα προβλέψιμο: εάν μια μέθοδος δεν έχει σημανθεί ως mutating, έχετε εγγύηση ότι δεν θα τροποποιήσετε τη δομή.
Όταν προσθέτετε τη λέξη-κλειδί mutating πριν από τη μέθοδο, η Swift αποκτά τη δυνατότητα να γράψει νέες τιμές στις ιδιότητες της δομής. Στην πραγματικότητα, η μέθοδος μπορεί ακόμα και να αντικαταστήσει πλήρως το στιγμιότυπο της δομής με ένα νέο μέσω του self = . Αυτός ο μηχανισμός χρησιμοποιείται, για παράδειγμα, στους τύπους Option και Result.
// Struct με μέθοδο mutating
struct Counter {
private var value: Int = 0
// Μέθοδος mutating — μπορεί να τροποποιήσει ιδιότητες
mutating func increment() {
value += 1
}
// Η μέθοδος mutating μπορεί να αντικαταστήσει πλήρως το self
mutating func reset() {
self = Counter()
}
// Μέθοδος non-mutating — μόνο για ανάγνωση
func currentValue() -> Int {
return value
}
}
var counter = Counter()
counter.increment()
print(counter.currentValue()) // 1
counter.reset()
print(counter.currentValue()) // 0
Κανόνες για mutating: η δομή πρέπει να δηλώνεται με var, όχι let — σε μια σταθερή δομή δεν μπορεί να κληθεί μέθοδος mutating. Ο μεταγλωττιστής το ελέγχει κατά τη φάση μεταγλώττισης: η προσπάθεια κλήσης μεθόδου mutating σε μια σταθερά let θα οδηγήσει σε σφάλμα μεταγλώττισης.
Η επιλογή μεταξύ struct και class — μία από τις θεμελιώδεις αποφάσεις στη Swift. Και οι δύο τύποι μπορούν να περιέχουν ιδιότητες, μεθόδους, αρχικοποιητές και να υλοποιούν πρωτόκολλα, αλλά έχουν θεμελιώδεις διαφορές στη σημασιολογία μνήμης, την κληρονομικότητα και τη διαχείριση κύκλου ζωής.
| Χαρακτηριστικό | struct | class |
|---|---|---|
| Τύπος | Value type (αντιγράφεται) | Reference type (αναφορά) |
| Κληρονομικότητα | Δεν υποστηρίζει | Υποστηρίζει |
| ARC / μέτρηση αναφορών | Δεν απαιτείται | Απαιτεί ARC |
| Αποαρχικοποίηση | Δεν υποστηρίζει | Υποστηρίζει deinit |
| Τροποποίηση ιδιοτήτων σε σταθερά | Μόνο μέσω var | Μπορεί μέσω let (η αναφορά είναι σταθερή) |
| Μετατροπή τύπου | Δεν υποστηρίζει | Υποστηρίζει |
| Αποθήκευση σε συλλογές | Αποθηκεύεται άμεσα (τιμή) | Αποθηκεύεται ως αναφορά (δείκτης) |
Οι δομές είναι προτιμότερες όταν τα δεδομένα δεν απαιτούν κληρονομικότητα, δεν πρέπει να έχουν κοινή ταυτότητα (π.χ. συντεταγμένες, διαστάσεις, διαμόρφωση) και μεταβιβάζονται μεταξύ μονάδων. Οι κλάσεις επιλέγονται για στοιχεία UI (UIView, UIViewController), singleton και αντικείμενα με κοινή ταυτότητα.
Η Apple συνιστά τη χρήση του struct ως προεπιλεγμένου τύπου για τη μοντελοποίηση δεδομένων στη Swift. Οι δομές είναι κατάλληλες για τα περισσότερα σενάρια χάρη στην προβλέψιμη σημασιολογία αντιγραφής και την απουσία επιβάρυνσης για μέτρηση αναφορών. Ας εξετάσουμε τις τυπικές περιπτώσεις όπου το struct είναι η βέλτιστη επιλογή.
Εάν η οντότητα περιέχει δεδομένα χωρίς ανάγκη κληρονομικότητας (Product, User, Order, Point), χρησιμοποιήστε struct. Ο μεταγλωττιστής δημιουργεί αυτόματα memberwise initializer — δεν χρειάζεται να γράψετε init χειροκίνητα. Τα Equatable και Hashable υλοποιούνται επίσης αυτόματα για δομές των οποίων όλες οι ιδιότητες πληρούν αυτά τα πρωτόκολλα.
Για διαμορφώσεις, ρυθμίσεις και σημαίες που δεν αλλάζουν μετά τη δημιουργία, το struct είναι προτιμότερο από το class. Μια σταθερή (let) δομή εγγυάται την αμεταβλητότητα όλων των ένθετων πεδίων — στο class αυτό ισχύει μόνο για την αναφορά, όχι για το περιεχόμενο του αντικειμένου.
Οι δομές είναι ασφαλείς σε πολυνηματικό περιβάλλον λόγω της value semantics. Κάθε νήμα λαμβάνει ένα ανεξάρτητο αντίγραφο δεδομένων και δεν επηρεάζει άλλα νήματα. Συνθήκες ανταγωνισμού μεταξύ νημάτων είναι αδύνατες για value types, καθιστώντας το struct την προτιμώμενη επιλογή για μοντέλα στο SwiftUI (το ObservableObject απαιτεί class, αλλά το @State χρησιμοποιεί struct).
// Παράδειγμα χρήσης struct για μοντέλο δεδομένων
struct User: Codable, Identifiable {
let id: UUID
var name: String
var email: String
var isPremium: Bool
// Υπολογιζόμενη ιδιότητα — non-mutating
var displayName: String {
isPremium ? "\(name) ⭐️" : name
}
}
// Αυτόματος memberwise αρχικοποιητής
let user = User(
id: UUID(),
name: "Alice",
email: "alice@example.com",
isPremium: true
)
// Η αντιγραφή είναι ασφαλής για πολυνηματικότητα
var userCopy = user
userCopy.isPremium = false
// Το user.isPremium παραμένει true
Χρησιμοποιήστε class όταν χρειάζεστε κληρονομικότητα (στοιχεία UIKit/AppKit), κοινή ταυτότητα (delegate, observer) ή ελεγχόμενο κύκλο ζωής αντικειμένων (deinit). Για οτιδήποτε άλλο — struct.
Συχνές Ερωτήσεις
Struct στη Swift — είναι ένας τύπος-τιμής (value type) που αντιγράφεται κατά τη μεταφορά μεταξύ τμημάτων κώδικα. Οι δομές μπορούν να περιέχουν ιδιότητες, μεθόδους, αρχικοποιητές και να υλοποιούν πρωτόκολλα. Οι βασικοί τύποι Swift (Int, String, Array) υλοποιούνται ως δομές.
Struct — value type (αντιγράφεται κατά την ανάθεση), δεν υποστηρίζει κληρονομικότητα και δεν απαιτεί ARC. Class — reference type (μεταβιβάζεται μέσω αναφοράς), υποστηρίζει κληρονομικότητα, αποαρχικοποίηση και μέτρηση αναφορών. Οι προγραμματιστές συνιστούν το struct ως προεπιλεγμένο τύπο.
Mutating — η λέξη-κλειδί που υποδεικνύει ότι η μέθοδος της δομής μπορεί να τροποποιήσει τις ιδιότητές της. Χωρίς mutating, ο μεταγλωττιστής απαγορεύει την τροποποίηση πεδίων. Οι μέθοδοι mutating μπορούν να κληθούν μόνο σε μεταβλητές που δηλώνονται με var, όχι let.
Copy-on-Write (COW) — βελτιστοποίηση Swift για δομές, όπου η πραγματική αντιγραφή δεδομένων αναβάλλεται μέχρι τη στιγμή της πρώτης μετάλλαξης. Όσο όλες οι μεταβλητές διαβάζουν μόνο τη δομή, μοιράζονται μία περιοχή μνήμης. Αυτό βελτιώνει την απόδοση κατά την εργασία με μεγάλες συλλογές.
Χρησιμοποιήστε struct για μοντέλα δεδομένων χωρίς κληρονομικότητα, διαμορφώσεις, DTO και πολυνηματικά σενάρια. Χρησιμοποιήστε class για στοιχεία UI UIKit/AppKit, singleton, οντότητες με κοινή ταυτότητα (delegate, observer) και αντικείμενα που απαιτούν αποαρχικοποίηση.
Σύνοψη
Θα αναπτύξουμε μια εφαρμογή για κινητά έτοιμη για χρήση
Η IT Sectr δημιουργεί εφαρμογές iOS και Android για νεοφυείς επιχειρήσεις και επιχειρήσεις από το 2017. Θα σας συμβουλεύσουμε και θα προτείνουμε την καλύτερη λύση.
Διαβάστε επίσης