Swift プロパティ

Swift のプロパティは、値を特定のクラス、構造体、または列挙型に関連付けます。

プロパティは格納プロパティと計算プロパティに分類できます:

格納プロパティ 計算プロパティ
インスタンスの一部として定数または変数を格納します 値を格納せずに計算します
クラスと構造体で使用されます クラス、構造体、および列挙型で使用されます

格納プロパティと計算プロパティは通常、特定の型のインスタンスに使用されます。

プロパティは型自体にも直接使用でき、このようなプロパティを型プロパティと呼びます。

さらに、プロパティオブザーバーを定義してプロパティ値の変化を監視し、それによってカスタム操作をトリガーすることもできます。プロパティオブザーバーは、自分で書いた格納プロパティにも、親クラスから継承したプロパティにも追加できます。


格納プロパティ

簡単に言うと、格納プロパティとは、特定のクラスまたは構造体のインスタンスに格納される定数または変数のことです。

格納プロパティは、変数格納プロパティ(キーワード var で定義)にも、定数格納プロパティ(キーワード let で定義)にもできます。

  • 格納プロパティを定義するときにデフォルト値を指定できます

  • また、構築プロセス中に格納プロパティの値を設定または変更でき、定数格納プロパティの値も変更できます

import Cocoa

struct Number
{
   var digits: Int
   let pi = 3.1415
}

var n = Number(digits: 12345)
n.digits = 67

print("\(n.digits)")
print("\(n.pi)")

上記のプログラムを実行すると、出力結果は次のようになります:

67
3.1415

以下のコードを考えてみましょう:

let pi = 3.1415

コード内の pi は、格納プロパティを定義するときにデフォルト値(pi = 3.1415)が指定されているため、いつ構造体をインスタンス化しても、その値は変わりません。

定義したのが定数格納プロパティの場合、それを変更しようとするとエラーになります。次のようになります:

import Cocoa

struct Number
{
    var digits: Int
    let numbers = 3.1415
}

var n = Number(digits: 12345)
n.digits = 67

print("\(n.digits)")
print("\(n.numbers)")
n.numbers = 8.7

上記のプログラムを実行するとエラーが発生します。エラーは次のとおりです:

error: cannot assign to property: 'numbers' is a 'let' constant
n.numbers = 8.7

これは、'numbers' が定数であり、変更できないことを意味します。


遅延格納プロパティ

遅延格納プロパティとは、最初に呼び出されたときに初期値が計算されるプロパティのことです。

プロパティ宣言の前にlazyを使用して、遅延格納プロパティを示します。

注意:
遅延格納プロパティは変数として宣言する必要があります(varキーワードを使用)。プロパティの値はインスタンスの構築が完了する前に取得できない可能性があるためです。定数プロパティは構築プロセスが完了する前に初期値が必要なため、遅延プロパティとして宣言することはできません。

遅延格納プロパティは通常、次の目的で使用されます:

  • オブジェクトの作成を遅延させること。

  • プロパティの値が他の未知のクラスに依存する場合

import Cocoa

class sample {
    lazy var no = number() // `var` 关键字是必须的
}

class number {
    var name = "サンプル Swift 教程"
}

var firstsample = sample()
print(firstsample.no.name)

上記のプログラムを実行すると、出力結果は次のようになります:

サンプル Swift 教程

インスタンス変数

Objective-C の経験があれば、Objective-C がクラスインスタンスに値と参照を格納するための2つの方法を提供していることをご存知でしょう。プロパティについても、インスタンス変数をプロパティ値のバックエンドストレージとして使用できます。

Swift プログラミング言語では、これらの理論をプロパティとして統一的に実装しています。Swift のプロパティには対応するインスタンス変数がなく、プロパティのバックエンドストレージに直接アクセスすることもできません。これにより、さまざまなシナリオでのアクセス方法の煩わしさが回避され、プロパティの定義が1つのステートメントに簡素化されます。

型内のプロパティのすべての情報(名前、型、メモリ管理の特性を含む)は、ただ1つの場所(型定義内)で定義されます。


計算プロパティ

格納プロパティの他に、クラス、構造体、列挙型は計算プロパティを定義できます。計算プロパティは値を直接格納せず、値を取得する getter と、他のプロパティや変数の値を間接的に設定するオプションの setter を提供します。

import Cocoa

class sample {
    var no1 = 0.0, no2 = 0.0
    var length = 300.0, breadth = 150.0
    
    var middle: (Double, Double) {
        get{
            return (length / 2, breadth / 2)
        }
        set(axis){
            no1 = axis.0 - (length / 2)
            no2 = axis.1 - (breadth / 2)
        }
    }
}

var result = sample()
print(result.middle)
result.middle = (0.0, 10.0)

print(result.no1)
print(result.no2)

上記のプログラムを実行すると、出力結果は次のようになります:

(150.0, 75.0)
-150.0
-65.0

計算プロパティの setter に新しい値を表すパラメータ名が定義されていない場合、デフォルト名の newValue を使用できます。


読み取り専用計算プロパティ

getter のみで setter がない計算プロパティは、読み取り専用計算プロパティです。

読み取り専用計算プロパティは常に値を返し、ドット(.)演算子でアクセスできますが、新しい値は設定できません。

import Cocoa

class film {
    var head = ""
    var duration = 0.0
    var metaInfo: [String:String] {
        return [
            "head": self.head,
            "duration":"\(self.duration)"
        ]
    }
}

var movie = film()
movie.head = "Swift 属性"
movie.duration = 3.09

print(movie.metaInfo["head"]!)
print(movie.metaInfo["duration"]!)

上記のプログラムを実行すると、出力結果は次のようになります:

Swift 属性
3.09

注意:

必ずvarキーワードを使用して計算プロパティを定義する必要があります。読み取り専用計算プロパティも含みます。これらの値は固定されていないためです。letキーワードは定数プロパティを宣言するためだけに使用され、初期化後に変更できない値を表します。


プロパティオブザーバー

プロパティオブザーバーはプロパティ値の変化を監視して応答します。プロパティに値が設定されるたびにプロパティオブザーバーが呼び出され、新しい値が現在の値と同じ場合でも例外ではありません。

遅延格納プロパティ以外の格納プロパティにはプロパティオブザーバーを追加できます。また、プロパティのオーバーライドによって、継承したプロパティ(格納プロパティと計算プロパティを含む)にもプロパティオブザーバーを追加できます。

注意:
オーバーライドできない計算プロパティにプロパティオブザーバーを追加する必要はありません。setter を通じて値の変化を直接監視して応答できるためです。

プロパティには、次の1つまたはすべてのオブザーバーを追加できます:

  • willSet新しい値が設定される前に呼び出されます
  • didSet新しい値が設定された直後に呼び出されます
  • willSet と didSet オブザーバーは、プロパティの初期化プロセス中には呼び出されません
import Cocoa

class Samplepgm {
    var counter: Int = 0{
        willSet(newTotal){
            print("计数器: \(newTotal)")
        }
        didSet{
            if counter > oldValue {
                print("新增数 \(counter - oldValue)")
            }
        }
    }
}
let NewCounter = Samplepgm()
NewCounter.counter = 100
NewCounter.counter = 800

上記のプログラムを実行すると、出力結果は次のようになります:

计数器: 100
新增数 100
计数器: 800
新增数 700

グローバル変数とローカル変数

計算プロパティとプロパティオブザーバーで説明したパターンは、グローバル変数とローカル変数にも使用できます。

ローカル変数 グローバル変数
関数、メソッド、またはクロージャの内部で定義される変数。 関数、メソッド、クロージャ、または任意の型の外部で定義される変数。
値の格納と取得に使用されます。 値の格納と取得に使用されます。
格納プロパティは値の取得と設定に使用されます。 格納プロパティは値の取得と設定に使用されます。
計算プロパティにも使用されます。 計算プロパティにも使用されます。

型プロパティ

型プロパティは、型定義の一部として、型の最も外側の波括弧({})内に記述されます。

値型の型プロパティを定義するにはキーワード static を使用し、クラスの型プロパティを定義するにはキーワード class を使用します。

struct Structname {
   static var storedTypeProperty = " "
   static var computedTypeProperty: Int {
      // 这里返回一个 Int 值
   }
}

enum Enumname {
   static var storedTypeProperty = " "
   static var computedTypeProperty: Int {
      // 这里返回一个 Int 值
   }
}

class Classname {
   class var computedTypeProperty: Int {
      // 这里返回一个 Int 值
   }
}

注意:
例の計算型プロパティは読み取り専用ですが、読み書き可能な計算型プロパティも定義できます。インスタンスの計算プロパティと同様の構文です。


型プロパティの値の取得と設定

インスタンスのプロパティと同様に、型プロパティへのアクセスもドット演算子(.)を使用して行います。ただし、型プロパティはインスタンスではなく、型自体を通じて取得および設定されます。例は次のとおりです:

import Cocoa

struct StudMarks {
   static let markCount = 97
   static var totalCount = 0
   var InternalMarks: Int = 0 {
      didSet {
         if InternalMarks > StudMarks.markCount {
            InternalMarks = StudMarks.markCount
         }
         if InternalMarks > StudMarks.totalCount {
            StudMarks.totalCount = InternalMarks
         }
      }
   }
}

var stud1Mark1 = StudMarks()
var stud1Mark2 = StudMarks()

stud1Mark1.InternalMarks = 98
print(stud1Mark1.InternalMarks) 

stud1Mark2.InternalMarks = 87
print(stud1Mark2.InternalMarks)

上記のプログラムを実行すると、出力結果は次のようになります:

97
87
その他の拡張