---
title: Özellikler
source: 'https://academia.sh/tr/kurslar/swift/ozellikler'
course: 'Swift Dili'
language: tr
updated: '2026-10-21T05:03:13+00:00'
license: 'CC BY-SA 4.0'
objectives:
    - 'Saklanan, hesaplanan ve gözlemleyen özelliğin değerini ne zaman kurduğunu ayırt eder'
    - 'lazy özelliğin ilk okumada bir kez değerlendirildiğini ölçer'
    - 'Varsayılan değer ile lazy arasındaki farkı örnek oluşturulurken görünen çıktıdan okur'
    - 'Yapıdaki lazy özelliğin kopyayla birlikte çoğaldığını gösterir'
---

# Özellikler

Saklanan, hesaplanan ve gözlemleyen özelliğin, lazy özelliğin ve static let değerinin ne zaman kurulduğunun ölçümü.

Önceki ders numaralandırmaların ilişkili değerinin durum kurulurken bir kez, hesaplanan özelliğinin ise her okunuşta değerlendirildiğini gösterdi. Aynı ayrım yalnız numaralandırmaya özgü değildir. Yapının, sınıfın ve numaralandırmanın **özellikleri (properties)** bir tipin verisini adlandırır ve her özellik kendi değerini kendi zamanında kurar. Bazısı örnek oluşturulurken, bazısı her okunuşta, bazısı ilk okunuşta.

Bu derste özelliğin dört çeşidi ölçülür. **Saklanan özellik (stored property)** bir değeri örneğin içinde tutar. **Hesaplanan özellik (computed property)** değer saklamaz, okunuşta bir ifade koşturur. **Gözlemleyen özellik (observed property)**, değişiminden önce ve sonra `willSet` ile `didSet` **gözlemcilerini (property observer)** çalıştıran saklanan özelliktir. **Tembel özellik (lazy property)** ilk okunuşa kadar değerini kurmaz. Kursun ölçü ekseni bu derste de aynıdır: **bu ifade ne zaman değerlendiriliyor?** Dört an vardır: hemen, ilk kullanımda, her kullanımda, hiç. `Probe` sınıfı aşağıda olduğu gibi verilir.

## Çekirdek

Her ders aynı çekirdeği kullanır. `Probe` bir ifadenin kaç kez değerlendirildiğini (`eval`) ve kaç kez kullanıldığını (`use`) sayar; `moment` özelliği bu iki sayıdan anı çıkarır. Açılış dersindeki bağlayıcı ölçümde sekiz ifadenin dağılımı 2/1/3/2 idi: ikisi hemen, biri ilk kullanımda, üçü her kullanımda, ikisi hiç. Bu derste yalnız kendi kesitini ölçeriz.

```swift
// Probe.swift — bir ifadenin ne zaman degerlendirildigini kaydeder
final class Probe {
    let label: String
    private(set) var evaluations = 0
    private(set) var uses = 0
    private var evaluatedBeforeUse = false

    init(_ label: String) {
        self.label = label
    }

    func eval<T>(_ value: T) -> T {
        evaluations += 1
        if uses == 0 { evaluatedBeforeUse = true }
        return value
    }

    func use<T>(_ access: () -> T) -> T {
        uses += 1
        return access()
    }

    var moment: String {
        if evaluations == 0 { return "hic" }
        if evaluations > 1 { return "her-kullanimda" }
        return evaluatedBeforeUse ? "hemen" : "ilk-kullanimda"
    }

    func report() {
        print("\(label): \(evaluations) degerlendirme, \(uses) kullanim -> \(moment)")
    }
}

func tally(_ probes: [Probe]) {
    for moment in ["hemen", "ilk-kullanimda", "her-kullanimda", "hic"] {
        let count = probes.filter { $0.moment == moment }.count
        print("\(moment): \(count)")
    }
}
```

## Üç Temel Çeşit

İlk ölçümde saklanan, hesaplanan ve gözlemleyen özellik yan yana durur. `Rectangle` yapısındaki `width` ve `height` saklanan, `area` ise hesaplanan özelliktir: bir değer tutmaz, her okunuşta çarpmayı yapar. `Thermostat` sınıfındaki `target` saklanan bir özelliktir ve `willSet` ile `didSet` gözlemcileri taşır. `willSet` değer yazılmadan önce gelecek değeri `newValue` adıyla, `didSet` yazıldıktan sonra eski değeri `oldValue` adıyla görür.

```swift
// main.swift — saklanan, hesaplanan ve gozlemleyen ozellik
struct Rectangle {
    var width: Int
    var height: Int

    var area: Int {
        width * height
    }
}

final class Thermostat {
    var target = 20 {
        willSet { print("willSet", target, "->", newValue) }
        didSet { print("didSet", oldValue, "->", target) }
    }

    init(target: Int) {
        self.target = target
    }
}

let rect = Rectangle(width: 3, height: 4)
print(rect.area)
let thermostat = Thermostat(target: 18)
print("baslatici bitti")
thermostat.target = 22
thermostat.target = 25
```

```
12
baslatici bitti
willSet 18 -> 22
didSet 18 -> 22
willSet 22 -> 25
didSet 22 -> 25
```

İlk satır `area` özelliğinin `3 * 4` sonucunu verir. İkinci satırdan önce başlatıcı `target` alanına `18` yazmıştı, ama gözlemciler çalışmadı: başlatıcı bitene kadar bir satır görünmedi. Gözlemciler yalnızca örnek tam kurulduktan sonraki atamalarda çalışır; tipin kendi başlatıcısındaki atama onları tetiklemez. Sonraki iki atama gözlemcileri çalıştırdı ve her atama için sıra `willSet`, atama, `didSet` oldu. `willSet` çıktısındaki sağ değer gelecek değeri, `didSet` çıktısındaki sol değer eski değeri gösterir; ikincisi `target` zaten güncellenmiş olduğundan, `oldValue` adı olmadan eski değere ulaşılamazdı.

Üç çeşit üç farklı soruya yanıt verir. Saklanan özellik "değer nerede duruyor?" sorusunu yanıtlar. Hesaplanan özellik "değer başka değerlerden nasıl türer?" sorusunu yanıtlar. Gözlemleyen özellik "değer değiştiğinde ne olmalı?" sorusunu yanıtlar. Hiçbiri tembel değildir: saklanan değer kurulurken, hesaplanan değer her okunuşta, gözlemci her yazımda çalışır.

**TS18.** Bu ölçüm bir yapıdaki hesaplanan, bir sınıftaki gözlemleyen özellik için. Yapıdaki gözlemciler, hesaplanan özelliğin değişim yönü ve gözlemcilerin `inout` ile geçirilen özellikte davranışı ayrıca ölçülmedi.

## Hesaplanan Özellik ve set

Hesaplanan özellik yalnızca okunmaz, yazılabilir de. Bunun için `get` yanına bir `set` yazılır; `set` atanan değeri `newValue` adıyla alır ve bunu saklanan özelliklere yansıtmakla yükümlüdür. `Temperature` yapısında `fahrenheit` ne bir değer saklar ne de kendisi bir kaynaktır. Okunduğunda `celsius`'tan türer, yazıldığında `celsius`'u günceller.

```swift
// main.swift — hesaplanan ozellik get ve set ile saklanan alana baglanir
struct Temperature {
    var celsius: Double

    var fahrenheit: Double {
        get { celsius * 9 / 5 + 32 }
        set { celsius = (newValue - 32) * 5 / 9 }
    }
}

var reading = Temperature(celsius: 100)
print(reading.fahrenheit)
reading.fahrenheit = 32
print(reading.celsius)
```

```
212.0
0.0
```

`celsius` `100` iken `fahrenheit` okunduğunda `212.0` çıktı. Sonra `fahrenheit`'a `32` yazıldı ve `set` bloğu `celsius`'u `0.0`'a çekti. Tek bir veri, iki ayrı gösterimle okunup yazılabiliyor ve gerçek değer tek bir yerde, `celsius` alanında duruyor. Hesaplanan özelliğin gücü budur: tutarsızlığa yol açmadan aynı bilginin iki ayrı biçimini sunar.

Önceki dersteki numaralandırma örneğinden aynı sonuç çıkar: hesaplanan özellik her okunuşta yeniden koşar. Burada fark, `set` ile geri yönde de çalışmasıdır.

## Tembel Özellik

Bazı özellikler pahalıdır ve her örnekte gerekmez. Örnek oluşturulurken hesaplanmaları, hiç okunmayacak bir örnek için boşa gidecek iştir. `lazy` anahtar sözcüğü özelliği, ilk okunuşa kadar kurulmamış bırakır. İlk okuma ifadeyi bir kez değerlendirir, sonucu özelliğin içinde saklar ve sonraki okumalar saklı değeri verir. `Report` sınıfındaki `summary` özelliği satırların toplamını tembel olarak hesaplar.

```swift
// main.swift — lazy ozellik ilk okumada bir kez degerlendirilir
final class Report {
    let probe: Probe
    var rows = [1, 2, 3]
    lazy var summary: Int = probe.eval(rows.reduce(0, +))

    init(probe: Probe) {
        self.probe = probe
    }
}

let summaryProbe = Probe("lazy-ilk-okuma")
let report = Report(probe: summaryProbe)
_ = summaryProbe.use { report.summary }
_ = summaryProbe.use { report.summary }
summaryProbe.report()
```

```
lazy-ilk-okuma: 1 degerlendirme, 2 kullanim -> ilk-kullanimda
```

Bir değerlendirme, iki okuma, an **ilk kullanımda**. Hesaplama ilk okuyuşta yapıldı ve ikinci okuyuş saklı sonucu verdi. Bunu hesaplanan özellikten ayıran şey budur: hesaplanan özellik iki okuyuşta iki değerlendirme yapardı. `lazy` ise bir hesaplanan özellik değildir, ertelenmiş bir saklanan özelliktir. Bu yüzden `lazy` bir `var` olmak zorundadır; ilk okuma değeri özelliğe yazdığı için, yazılabilir bir saklanan özellik gerekir.

## Varsayılan Değer ile lazy Arasındaki Fark

Önceki derste varsayılan değerin her örnekte bir kez değerlendirildiğini ölçtük. Şimdi aynı ifadeyi iki biçimde yazalım ve fark görünür olsun. `Ticket` sınıfı iki özellik taşır: `eagerId` bir varsayılan değerle, `lazyId` `lazy` ile aynı `makeId` işlevini çağırır ve işlev her çağrıldığında bir satır yazdırır. İki bilet oluşturulur, ardından yalnızca ilk biletin `lazyId` özelliği iki kez okunur.

```swift
// main.swift — varsayilan deger olusturmada, lazy ilk okumada
func makeId(_ kind: String) -> Int {
    print("uretildi", kind)
    return 7
}

final class Ticket {
    var eagerId = makeId("hemen")
    lazy var lazyId = makeId("tembel")
}

let tickets = [Ticket(), Ticket()]
print("olusturuldu")
print(tickets[0].lazyId)
print(tickets[0].lazyId)
```

```
uretildi hemen
uretildi hemen
olusturuldu
uretildi tembel
7
7
```

İlk iki satır, iki biletin `eagerId` özelliğinin `olusturuldu` yazılmadan önce kurulduğunu gösterir: her örnek kendi varsayılan değerini oluşturma anında hesapladı. `lazyId` için bu satırlar yok. `tembel` satırı ancak `tickets[0].lazyId` ilk okunduğunda göründü ve yalnız bir kez göründü; ikinci okuma `7`'yi saklı değerden verdi. İkinci biletin `lazyId` özelliği hiç okunmadığı için hiç kurulmadı.

Fark kısaca şöyle özetlenir. Varsayılan değerin ifadesi her örnek için, örnek oluşurken koşar. `lazy` ifadesi, yalnızca okunan örnekler için, ilk okunuşta koşar. Yirmi bilet oluşturulup yalnızca birinin kimliğine bakılıyorsa `lazy` yirmi yerine bir hesap yapar.

## static let

Tipe ait değerler, yani `static` özellikler, örneklere değil tipin kendisine bağlıdır. `static let` ile tanımlanan bir değer tembeldir: ilk erişimde kurulur ve bir kez kurulur. `Config.version` bir kapanışla oluşturulur ve kapanış her çalıştığında bir satır yazdırır.

```swift
// main.swift — static let ilk erisimde kurulur
enum Config {
    static let version: String = {
        print("static let kuruldu")
        return "1.0"
    }()
}

print("once")
print(Config.version)
print(Config.version)
```

```
once
static let kuruldu
1.0
1.0
```

`once` satırı ilk erişimden önce yazıldı; `static let kuruldu` satırı ancak `Config.version` ilk okunduğunda göründü ve yalnız bir kez göründü. Sonraki okuma `1.0` değerini saklı kopyadan verdi. Bu, `lazy` ile aynı davranıştır, ama bir fark vardır: `static let` bir örneğe bağlı değildir ve `lazy` gibi `var` olmak zorunda değildir, bu yüzden değişmez bir tembel sabit olarak kullanılabilir.

**TS19.** Bu ölçüm bir kapanışla kurulan `static let` için. `static var` ve `static` hesaplanan özellikler ayrıca ölçülmedi.

## Sınırlayıcı Ölçüm

`lazy` özellik için kurduğumuz kural şu: ifade ilk okunuşta bir kez değerlendirilir. Bu kural bir sınıf örneği için doğrudur, çünkü sınıf örneği paylaşılan tek bir nesnedir. Aynı özelliği bir yapıya taşıyalım. Yapılar atamada kopyalanır ve kopya henüz okunmamış bir `lazy` özelliğin kendi kopyasını taşır. `Sheet` yapısında `total` tembel bir özelliktir; `sheetA` kopyalanır ve iki kopya da bir kez okunur.

```swift
// main.swift — yapidaki lazy ozellik kopyayla coaltir
struct Sheet {
    let probe: Probe
    var rows = [1, 2, 3]
    lazy var total: Int = probe.eval(rows.reduce(0, +))
}

let sheetProbe = Probe("yapi-lazy-kopya")
var sheetA = Sheet(probe: sheetProbe)
var sheetB = sheetA
_ = sheetProbe.use { sheetA.total }
_ = sheetProbe.use { sheetB.total }
sheetProbe.report()
```

```
yapi-lazy-kopya: 2 degerlendirme, 2 kullanim -> her-kullanimda
```

İki okuma, iki değerlendirme, an **her kullanımda**. İki kopya da aynı `lazy` özelliği ayrı ayrı kurdu, çünkü kopyalama anında özellik henüz kurulmamıştı ve her kopya kendi kurulmamış özelliğini aldı. Aynı değer iki kez hesaplandı.

Bu sonuç dersin kuralını daraltır. "Bir kez" cümlesi, bir örnek için geçerlidir. Yapıda kopya sayısı kadar örnek vardır ve henüz okunmamış bir `lazy` özellik her kopyada bağımsız olarak ilk okunuşta kurulur. Sınıfta kopya oluşmadığı için bu durum doğmaz.

Yapıdaki `lazy` özelliğin ikinci bir sınırı vardır ve o da ölçülemez, çünkü derlenmez. Okuma, özelliğe yazdığı için yapının değiştirilebilir olmasını gerektirir. Aşağıdaki parça `let` ile tanımlanan bir yapının `lazy` özelliğini okur ve derlenmez: derleyici onu reddeder. Hata iletisi, `let` ile tanımlanan bir yapı üzerinde değiştirici okumanın kullanılamayacağını bildirdi. Parça burada yalnızca anlatım için durur.

```swift
struct Sheet2 {
    var rows = [1, 2, 3]
    lazy var total: Int = rows.reduce(0, +)
}
let fixed = Sheet2()
print(fixed.total)   // derlenmez: let yapida lazy ozellik okunamaz
```

Bu, `lazy` özelliğin bir yan sonucudur: okuma bir yazma içerir. Okuma amaçlı kullanılacak yapı örneğinin `var` olması gerekir. Sınıfta aynı kısıt yoktur, çünkü `let` sınıf adı yalnız adı sabitler, nesnenin içeriğini değil.

**TS20.** Bu ölçüm iki kopya ve tek bir `lazy` özellik için. İç içe yapılar, `lazy` özelliğin başka bir `lazy` özelliğe bağlı olduğu durumlar ve reddedilen parçada yalnızca `let` yapı denendi; başka sabitleme biçimleri denenmedi.

## Özet

- Saklanan özellik değeri kurulurken, hesaplanan özellik her okunuşta, gözlemci her yazımda çalışır; tipin kendi başlatıcısındaki atama gözlemcileri tetiklemez.
- Hesaplanan özellik `set` ile yazılabilir ve gerçek değeri başka bir saklanan özelliğe yansıtır.
- `lazy` özellik ilk okunuşta bir kez değerlendirilir; varsayılan değer ise her örnekte oluşturma sırasında koşar.
- `static let` ilk erişimde kurulur ve bir kez kurulur.
- Yapıdaki henüz okunmamış `lazy` özellik kopyayla birlikte çoğalır; `let` yapıda okunamaz.
- Bu dersin anı: **ilk kullanımda**. `lazy` özellik ilk okunuşta bir kez değerlendirilir.

## Sonraki Adım

Bu derste özelliklerin değerini ne zaman kurduğunu ölçtük. Tipler yalnız veri taşımaz, aynı zamanda davranış sözü de verebilir. Bir sonraki ders protokolleri ölçer: bir tipin hangi özellikleri ve yöntemleri sağlaması gerektiğini bildiren sözleşmeleri, ve sözleşmeyi kullanan koddan çağrıldığında özelliğin hangi anda değerlendirildiğini.
