class — τι είναι, βασικές έννοιες και αρχή λειτουργίας στο Swift

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

Class — είναι ένας τύπος αναφοράς (reference type) στη γλώσσα Swift, του οποίου τα στιγμιότυπα μεταδίδονται μέσω αναφοράς, όχι αντιγράφονται κατά την ανάθεση. Σε αντίθεση με τις δομές, οι κλάσεις υποστηρίζουν κληρονομικότητα, αποαρχικοποίηση και αυτόματη μέτρηση αναφορών ARC για διαχείριση μνήμης. Σύμφωνα με τον Swift Programming Language Guide, 2026, το class είναι απαραίτητο για εργασία με τα UI frameworks της Apple (UIKit, AppKit) και υλοποίηση προτύπων που απαιτούν κοινή ταυτότητα αντικειμένου. Η επιλογή μεταξύ class και struct είναι μία από τις βασικές αρχιτεκτονικές αποφάσεις στο Swift.

Κύρια σημεία

  • Class — reference type στο Swift, όπου η μεταβλητή αποθηκεύει μια αναφορά στο αντικείμενο στο heap, όχι την ίδια την τιμή.
  • Κληρονομικότητα — οι κλάσεις μπορούν να κληρονομήσουν ιδιότητες και μεθόδους της γονικής κλάσης και να τις παρακάμψουν μέσω override.
  • ARC — η αυτόματη μέτρηση αναφορών ελευθερώνει μνήμη όταν δεν απομένουν ισχυρές αναφορές στο αντικείμενο.
  • Deinit — ειδική μέθοδος που καλείται πριν από την απελευθέρωση του αντικειμένου για καθαρισμό πόρων.
  • Ταυτότητα — οι τελεστές === και !== ελέγχουν αν δύο μεταβλητές αναφέρονται στο ίδιο στιγμιότυπο της κλάσης.

Τι είναι το class στο Swift;

Class (κλάση) — είναι ένας σύνθετος τύπος αναφοράς στο Swift που ομαδοποιεί ιδιότητες και μεθόδους σε μια ενιαία οντότητα με υποστήριξη κληρονομικότητας και δυναμικής αποστολής. Σε αντίθεση με το struct, το στιγμιότυπο της κλάσης δημιουργείται στο heap, και η μεταβλητή αποθηκεύει μια αναφορά σε αυτό το στιγμιότυπο, όχι τα ίδια τα δεδομένα.

Όταν αναθέτετε μια μεταβλητή κλάσης σε άλλη μεταβλητή, και οι δύο αναφέρονται στο ίδιο αντικείμενο στη μνήμη. Οι αλλαγές μέσω μιας αναφοράς είναι ορατές μέσω της άλλης — αυτή είναι η θεμελιώδης ιδιότητα των reference types, που χρησιμοποιείται σε πρότυπα αντιπροσώπευσης, παρατήρησης και κοινής κατάστασης.

Σύμφωνα με την Apple Swift Documentation, οι κλάσεις είναι ο μόνος τρόπος εργασίας με UIKit και AppKit, όπου όλα τα UI components κληρονομούν από UIView και UIViewController. Επιπλέον, οι κλάσεις είναι απαραίτητες για την υλοποίηση προτύπων που απαιτούν ταυτότητα αντικειμένου (δύο αναφορές σε ένα αντικείμενο) και ελεγχόμενη διάρκεια ζωής.

Class ως reference type

Σημασιολογία reference type — η βασική ιδιότητα των κλάσεων. Κατά την ανάθεση μιας κλάσης σε μια νέα μεταβλητή, το Swift αντιγράφει την αναφορά, όχι τα δεδομένα. Όλες οι μεταβλητές που αναφέρονται στο ίδιο στιγμιότυπο βλέπουν την τρέχουσα κατάστασή του και μπορούν να την αλλάξουν. Αυτή η συμπεριφορά διαφέρει θεμελιωδώς από τα value types, όπου κάθε μεταβλητή λαμβάνει ένα ανεξάρτητο αντίγραφο.

swift
// Παράδειγμα σημασιολογίας reference type
class User {
    var name: String
    init(name: String) { self.name = name }
}

let user1 = User(name: "Alice")
let user2 = user1           // user2 — ίδια αναφορά
user2.name = "Bob"

print(user1.name)               // "Bob" — άλλαξε μέσω user2!

// Έλεγχος ταυτότητας με τον τελεστή ===
print(user1 === user2)          // true — ίδιο αντικείμενο

Οι τελεστές === (ταυτότητα) και !== ελέγχουν αν δύο μεταβλητές αναφέρονται στο ίδιο στιγμιότυπο κλάσης. Αυτή είναι η διαφορά από το == (ισότητα), που συγκρίνει τιμές ιδιοτήτων. Για το struct ο τελεστής === δεν είναι διαθέσιμος — τα value types δεν έχουν ταυτότητα.

Κληρονομικότητα κλάσεων

Κληρονομικότητα — ο μηχανισμός με τον οποίο μια κλάση μπορεί να κληρονομήσει ιδιότητες και μεθόδους της γονικής κλάσης. Στο Swift μια κλάση μπορεί να κληρονομήσει μόνο από έναν γονέα (single inheritance), αλλά μπορεί να υλοποιήσει πολλαπλά πρωτόκολλα. Η λέξη-κλειδί override επιτρέπει την παράκαμψη μιας κληρονομημένης μεθόδου ή ιδιότητας.

Βασική κλάση και υποκλάση

Κάθε κλάση που δεν κληρονομεί από άλλη κλάση γίνεται αυτόματα βασική (μην συγχέεται με το NSObject). Η υποκλάση υποδεικνύει τον γονέα με άνω τελεία μετά το όνομα. Εάν η υποκλάση παρακάμπτει τη μέθοδο του γονέα, πρέπει να καλέσει super.μέθοδο() για να διατηρήσει τη συμπεριφορά του γονέα — αυτό είναι απαίτηση του μεταγλωττιστή.

Final class

Η λέξη-κλειδί final πριν από το class απαγορεύει την κληρονομικότητα. Ο μεταγλωττιστής μπορεί να βελτιστοποιήσει τις κλήσεις μεθόδων των final κλάσεων μέσω static dispatch, βελτιώνοντας την απόδοση. Χρησιμοποιήστε final για κλάσεις που δεν προορίζονται για επέκταση — αυτό τεκμηριώνει την πρόθεσή σας και επιταχύνει τον κώδικα.

swift
// Παράδειγμα κληρονομικότητας κλάσεων στο Swift
class Vehicle {
    var speed: Double = 0

    func description() -> String {
        "Speed: \(speed) km/h"
    }
}

// Car κληρονομεί από Vehicle
class Car: Vehicle {
    var brand: String = "Unknown"

    override func description() -> String {
        "\(brand) - \(speed) km/h"
    }
}

// Final class — αποτρέπει κληρονομικότητα
final class ElectricCar: Car {
    var batteryLevel: Double = 100
}

let tesla = ElectricCar()
tesla.brand = "Tesla"
tesla.speed = 120
print(tesla.description())  // "Tesla - 120.0 km/h"

Η κληρονομικότητα κλάσεων είναι ένας ισχυρός αλλά υπεύθυνος μηχανισμός. Η βαθιά ιεραρχία (5+ επίπεδα) δυσκολεύει τη συντήρηση και τη δοκιμή. Για επαναχρησιμοποίηση λειτουργικότητας χωρίς κληρονομικότητα χρησιμοποιήστε πρωτόκολλα με extension και προγραμματισμό προσανατολισμένο σε πρωτόκολλα — μια προσέγγιση που η Apple προωθεί ως εναλλακτική για βαθιές ιεραρχίες κλάσεων.

Αποαρχικοποίηση και διαχείριση μνήμης

Το Swift χρησιμοποιεί ARC (Automatic Reference Counting) για τη διαχείριση μνήμης των κλάσεων. Κάθε στιγμιότυπο κλάσης έχει έναν μετρητή ισχυρών αναφορών. Κατά τη δημιουργία μιας νέας ισχυρής αναφοράς ο μετρητής αυξάνεται· κατά την καταστροφή — μειώνεται. Όταν ο μετρητής φτάσει στο μηδέν, η μνήμη ελευθερώνεται.

Deinit

Deinit — μέθοδος που καλείται αυτόματα πριν από την απελευθέρωση του στιγμιοτύπου της κλάσης. Σε αυτήν ελευθερώνονται πόροι: κλείνουν αρχεία, γίνεται απεγγραφή από ειδοποιήσεις, σταματούν χρονοδιακόπτες. Το deinit υπάρχει μόνο στις κλάσεις — οι δομές και οι απαριθμήσεις δεν το έχουν.

Αδύναμες και αδέσποτες αναφορές

Για την πρόληψη κύκλων ισχυρών αναφορών (retain cycles), το Swift παρέχει weak και unowned αναφορές. Weak — μια προαιρετική αναφορά που γίνεται αυτόματα nil κατά την απελευθέρωση του αντικειμένου. Unowned — μη προαιρετική, αλλά αναφέρεται σε ένα αντικείμενο που εγγυημένα ζει περισσότερο από το τρέχον πλαίσιο. Ένας τυπικός retain cycle προκύπτει στη σχέση parent-child: το child διατηρεί μια ισχυρή αναφορά στο parent.

swift
// Παράδειγμα ARC και αδύναμης αναφοράς
class Parent {
    var name: String
    var child: Child?

    init(name: String) { self.name = name }
    deinit { print("\(name) αποδεσμεύτηκε") }
}

class Child {
    var name: String
    weak var parent: Parent?   // weak αποτρέπει retain cycle

    init(name: String) { self.name = name }
    deinit { print("\(name) αποδεσμεύτηκε") }
}

var parent: Parent? = Parent(name: "Anna")
parent?.child = Child(name: "Mia")
parent?.child?.parent = parent

parent = nil  // Και τα δύο αντικείμενα αποδεσμεύτηκαν!
// Χωρίς weak θα δημιουργούσε retain cycle

Χρησιμοποιείτε πάντα weak για αναφορές από το θυγατρικό αντικείμενο προς το γονικό και για λίστες capture σε closures. Χρησιμοποιήστε unowned μόνο όταν είστε σίγουροι ότι το αντικείμενο θα επιζήσει του τρέχοντος πλαισίου — η λανθασμένη χρήση unowned μπορεί να οδηγήσει σε crash κατά την πρόσβαση σε απελευθερωμένη μνήμη.

Class vs Struct: βασικές διαφορές

Η επιλογή μεταξύ class και struct είναι μια αρχιτεκτονική απόφαση που επηρεάζει την απόδοση, την ασφάλεια νημάτων και τον σχεδιασμό API. Ας εξετάσουμε τον πίνακα βασικών διαφορών που θα βοηθήσει στη λήψη της σωστής απόφασης σε κάθε συγκεκριμένη περίπτωση.

Χαρακτηριστικόclassstruct
ΤύποςReference type (αναφορά)Value type (αντίγραφο)
ΜνήμηHeap + ARCStack / inline
ΚληρονομικότηταΥποστηρίζει (ένας γονέας)Δεν υποστηρίζει
DeinitΥπάρχειΔεν υπάρχει
Ταυτότητα (===)ΥποστηρίζειΔεν υποστηρίζει
MutatingΔεν απαιτείται (πάντα mutating)Μόνο με mutating
Memberwise initΔεν παράγεταιΠαράγεται αυτόματα
Ασφάλεια νημάτωνΔεν είναι εγγυημένη (κοινή κατάσταση)Εγγυημένη (αντιγραφή)

Χρησιμοποιήστε κλάσεις όταν χρειάζεστε κοινή ταυτότητα (πολλά μέρη κώδικα εργάζονται με ένα αντικείμενο), κληρονομικότητα ή αλληλεπίδραση με Objective-C runtime. Για όλα τα άλλα, προτιμώνται οι δομές — είναι ταχύτερες, ασφαλέστερες σε πολυνηματικό κώδικα και δεν απαιτούν διαχείριση μνήμης.

Πότε να χρησιμοποιείτε class στο Swift

Παρά τη σύσταση της Apple να χρησιμοποιείτε struct από προεπιλογή, οι κλάσεις είναι απαραίτητες σε μερικά συγκεκριμένα σενάρια. Ας εξετάσουμε το καθένα με πρακτικά παραδείγματα.

UIKit και AppKit components

Όλα τα UI components σε iOS και macOS είναι κλάσεις που κληρονομούν από UIView (iOS) ή NSView (macOS). Δεν μπορείτε να αντικαταστήσετε το UIViewController με μια δομή — απαιτεί κληρονομικότητα και deinit για την απελευθέρωση πόρων. Κατά την εργασία με UIKit χρησιμοποιήστε κλάσεις για controllers, views και τους delegates τους.

Singleton και κοινή κατάσταση

Το πρότυπο Singleton (ένα στιγμιότυπο κλάσης για ολόκληρη την εφαρμογή) απαιτεί σημασιολογία αναφοράς. Διαχειριστές: NetworkManager, SettingsManager, AnalyticsService — συνήθως υλοποιούνται ως κλάσεις με shared static property. Οι δομές δεν είναι κατάλληλες γιατί κάθε αντίγραφο θα ήταν ανεξάρτητο στιγμιότυπο.

Dependency Injection και αντικείμενα αναφοράς

Όταν ένα αντικείμενο πρέπει να είναι μοναδική πηγή αλήθειας (single source of truth) και μεταδίδεται μεταξύ μονάδων μέσω αναφοράς — χρησιμοποιήστε class. Αυτό αφορά τη διαχείριση κατάστασης όπου η αλλαγή του αντικειμένου σε ένα μέρος πρέπει να είναι ορατή σε όλα τα εξαρτώμενα components. Για ObservableObject στο SwiftUI οι κλάσεις είναι υποχρεωτικές.

swift
// ObservableObject — class απαραίτητο για SwiftUI
import SwiftUI

class AppViewModel: ObservableObject {
    @Published var isLoggedIn: Bool = false
    @Published var username: String = ""

    func login(user: String) {
        isLoggedIn = true
        username = user
    }
}

// Χρήση σε SwiftUI View
struct ContentView: View {
    @StateObject var viewModel = AppViewModel()

    var body: some View {
        Text(viewModel.isLoggedIn ? "Καλώς ήρθατε" : "Σύνδεση")
    }
}

Κανόνας: αν ένα αντικείμενο πρέπει να έχει ταυτότητα (δύο αναφορές -> ένα αντικείμενο), να είναι μοναδικό στιγμιότυπο ή να λειτουργεί με UIKit/Objective-C — επιλέξτε class. Αν το αντικείμενο απλώς αποθηκεύει δεδομένα — επιλέξτε struct.

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

Τι είναι το class στο Swift;

Class — είναι ένας τύπος αναφοράς (reference type) στο Swift που υποστηρίζει κληρονομικότητα, αποαρχικοποίηση και ARC για διαχείριση μνήμης. Τα στιγμιότυπα κλάσεων αποθηκεύονται στο heap και οι μεταβλητές περιέχουν μια αναφορά στο αντικείμενο, όχι το αντίγραφό του.

Σε τι διαφέρει το class από το struct στο Swift;

Class — reference type (μεταδίδεται μέσω αναφοράς), υποστηρίζει κληρονομικότητα και deinit. Struct — value type (αντιγράφεται), δεν υποστηρίζει κληρονομικότητα, αλλά υλοποιεί πρωτόκολλα και λαμβάνει αυτόματα memberwise init. Η Swift συνιστά το struct ως προεπιλεγμένο τύπο.

Τι είναι το ARC στο Swift;

ARC (Automatic Reference Counting) — μηχανισμός διαχείρισης μνήμης για τις κλάσεις Swift. Κάθε στιγμιότυπο έχει έναν μετρητή ισχυρών αναφορών. Όταν ο μετρητής φτάσει στο μηδέν, η μνήμη ελευθερώνεται. Οι weak και unowned αναφορές αποτρέπουν τους retain cycles μεταξύ αντικειμένων.

Τι είναι το deinit στο Swift;

Deinit — μέθοδος της κλάσης που καλείται αυτόματα πριν από την απελευθέρωση της μνήμης της. Χρησιμοποιείται για κλείσιμο αρχείων, απεγγραφή από ειδοποιήσεις και άλλες τελικές λειτουργίες. Το deinit υπάρχει μόνο στις κλάσεις — οι δομές δεν το έχουν.

Πότε να χρησιμοποιείτε class στο Swift;

Χρησιμοποιήστε class για UI components UIKit/AppKit, singleton, ObservableObject στο SwiftUI, αντικείμενα με κοινή ταυτότητα (delegate, observer) και κατά την εργασία με Objective-C runtime. Για μοντέλα δεδομένων, DTO και διαμορφώσεις προτιμάται το struct.

Σύνοψη

  • Class — είναι reference type στο Swift με σημασιολογία μετάδοσης μέσω αναφοράς: όλες οι μεταβλητές που δείχνουν στο ίδιο αντικείμενο βλέπουν την τρέχουσα κατάστασή του και μπορούν να την αλλάξουν.
  • ARC διαχειρίζεται τη μνήμη των κλάσεων μέσω μέτρησης ισχυρών αναφορών· weak και unowned αποτρέπουν κύκλους αναφορών σε parent-child και closures.
  • Κληρονομικότητα επιτρέπει στις κλάσεις να επαναχρησιμοποιούν και να παρακάμπτουν τη συμπεριφορά του γονέα, αλλά η βαθιά ιεραρχία (5+ επίπεδα) δυσκολεύει τη συντήρηση κώδικα.
  • Deinit εκτελείται κατά την απελευθέρωση του αντικειμένου και είναι υποχρεωτικό για την απελευθέρωση πόρων — αρχείων, χρονοδιακοπτών, συνδρομών NotificationCenter.
  • UIKit και AppKit απαιτούν κλάσεις για όλα τα UI components — UIView, UIViewController, τους delegates και data sources τους.
  • ObservableObject στο SwiftUI — το class είναι υποχρεωτικό, καθώς το SwiftUI παρακολουθεί αλλαγές μέσω @Published και @StateObject μέσω αναφοράς.
  • Η Apple συνιστά το struct ως προεπιλεγμένο τύπο για νέους τύπους δεδομένων — χρησιμοποιήστε class μόνο όταν απαιτείται ταυτότητα, κληρονομικότητα ή ενσωμάτωση με Objective-C.

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

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

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

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