Swift: Klasy
Składnia
Klasę w Swift tworzy się za pomocą słowa kluczowego class:
class MyClass {
var property1: String = ""
var property2: Int = 0
}
Tworzenie obiektów
Stworzenie instancji klasy wygląda tak:
var myObject = MyClass()
Dostęp do właściwości
Za pomocą . możesz dostać się do właściwości obiektów:
myObject.property1 = "Hello"
myObject.property2 = 7
print(myObject.property1) // Hello
print(myObject.property2) // 7
Metody
Do klasy można dodać także funkcje:
class User {
var firstName: String = ""
var lastName: String = ""
func getFullName() -> String {
return "\(firstName) \(lastName)"
}
}
var user = User()
user.firstName = "Jan"
user.lastName = "Kowalski"
print(user.getFullName()) // Jan Kowalski
Metody statyczne
Możesz dodać do klasy metodę statyczną:
class MyClass {
static func sumUp(_ data: [Int]) -> Int {
return data.reduce(0, +)
}
}
let result: Int = MyClass.sumUp([1, 2, 3])
print(result) // 6
Do metody statycznej można odwołać się tylko za pomocą nazwy klasy.
Konstruktor
Tak samo jak w strukturach możesz za pomocą init przekazać dane dla tworzonej instancji:
class User {
var firstName: String
var lastName: String
init(firstName: String, lastName: String) {
self.firstName = firstName
self.lastName = lastName
}
func getFullName() -> String {
return "\(firstName) \(lastName)"
}
}
var user = User(firstName: "Jan", lastName: "Kowalski")
print(user.getFullName()) // Jan Kowalski
Dziedziczenie
Swift pozwala także na dziedziczenie z innej klasy.
class BaseClass {
var propA: Int = 0
func doSomething1() {
print("Call doSomething1 from BaseClass")
}
}
class SubClass: BaseClass {
var propB: String = ""
func doSomething2() {
print("Call doSomething1 from SubClass")
}
}
var object = SubClass()
object.propA = 7
object.propB = "Some data"
object.doSomething1() // Call doSomething1 from BaseClass
object.doSomething2() // Call doSomething1 from SubClass
Klasa pochodna dziedziczy wszystkie właściwości i metody po klasie bazowej.
W Swift dziedziczyć można tylko po jednej klasie.
Nadpisanie metody rodzica
Jeśli klasa potomna używa takiej samej metody jak klasa bazowa (rodzic), to musisz użyć słowa kluczowego override.
class Shape {
func area() -> Double {
return 0.0
}
}
class Rectangle: Shape {
var a: Double = 0.0
var b: Double = 0.0
init(a: Double, b: Double) {
self.a = a
self.b = b
}
override func area() -> Double {
return a * b
}
}
class Square: Shape {
var a: Double = 0.0
init(a: Double) {
self.a = a
}
override func area() -> Double {
return a * a
}
}
var rect = Rectangle(a: 7.0, b: 5.0)
print(rect.area()) //
var square = Square(a: 10.0)
print(square.area())
Nadpisanie właściwości klasy
Jeśli klasa bazowa ma computed property możesz nadpisać ją w klasie potomnej.
class Product {
var price: Double {
return 0.0
}
}
class ProductA: Product {
override var price: Double {
return 500.0
}
}
class ProductB: Product {
override var price: Double {
return 1000.0
}
}
var productA = ProductA()
var productB = ProductB()
print(productA.price) // 500.0
print(productB.price)// 1000.0
Możesz nadpisać także property observers.
Uwaga: Nie można nadpisać "zwykłych" właściwości klasy:
class A {
var counter = 1
}
class B: A {
override var counter = 2 // Błąd!
}
Wywołanie metody rodzica
Jeśli potrzebujesz wywołać w metodzie podklasy metodę należącą do rodzica, użyj słowa kluczowego super.
class ParentClass {
func doSomething() {
print("ParentClass doSomething")
}
}
class ChildClass: ParentClass {
override func doSomething() {
super.doSomething()
print("ChildClass doSomething")
}
}
var childObject = ChildClass()
childObject.doSomething()
// ParentClass doSomething
// ChildClass doSomething
Za pomocą super można też dostać się do właściwości klasy.
Zapobieganie nadpisaniu
Jeżeli nie chcesz, żeby właściwość lub metoda klasy były nadpisane użyj słowa kluczowego final.
class ParentClass {
final func doSomething() {
print("ParentClass doSomething")
}
}
class ChildClass: ParentClass {
override func doSomething() {
super.doSomething()
print("ChildClass doSomething")
}
}
var childObject = ChildClass()
childObject.doSomething()
Przy takiej próbie zostanie zgłoszony błąd. final możesz użyć także do właściwości klasy.
Klasa to typ referencyjny
Każdy obiekt klasy to typ referencyjny. To znaczy, że zmienna, do której przypisany jest obiekt, zawiera referencję do instancji, a nie samą instancję.
Przykład:
class User {
var firstName: String
var lastName: String
init(firstName: String, lastName: String) {
self.firstName = firstName
self.lastName = lastName
}
func getFullName() -> String {
return "\(firstName) \(lastName)"
}
}
var user1 = User(firstName: "Jan", lastName: "Kowalski")
print(user1.getFullName()) // Jan Kowalski
var user2 = user1
print(user2.getFullName()) // Jan Kowalski
user1.firstName = "Grażyna"
user1.lastName = "Kowalska"
print(user2.getFullName()) // Grażyna Kowalska
Do zmiennej user2 przypisany został obiekt ze zmiennej user1. A tak naprawdę do user2 została przypisana referencja do obiektu, którą przechowuje user1. Więc zmiana danych poprzez user1 spowoduje, że user2 będzie wskazywać na te same dane.