クラス、構造体、列挙型について
Swift実践入門より引用
Swiftの型は、クラス、構造体、列挙型として定義できます。標準ライブラリの型の多くは構造体として定義されており、Cocoaのほとんどの型はクラスとして定義されています。 クラス、構造体、列挙型の3つには、メソッドやプロパティなどの共通の要素が用意されています。本章では、これらの共通要素について説明します。それぞれに固有の要素については次章で解説します。
代表的な型を構成する要素は、型が持つ値を保存するプロパティと、型の振る舞いを表すメソッドの2つです。プロパティは型に紐付いた変数や定数と言い換えることができ、メソッドは型に紐付いた関数と言い換えることができます。この2つに加えて、型を構成する要素には、初期化を行うイニシャライザ、コレクションの要素を取得するサブスクリプト、型内に型を定義するネスト型があります。 本章では、これらの型を構成する要素について説明します。
インスタンスとは型を実体化したものであり、型に定義されているプロパティやメソッドを持ちます。たとえば、String型の値"abc"はString型のインスタンスであり、append(_:)メソッドなどを持ちます。
struct 構造体名 {
構造体の定義
}
クラス
class クラス名 {
クラスの定義
}
列挙型
enum 列挙型名 {
列挙型の定義
}
型の内部でのインスタンスへのアクセス 型の内部のプロパティやメソッドなどの中では、selfキーワードを通じてインスタンス自身にアクセスできます。 次の例では、SomeStruct型のprintValue()メソッドで、インスタンス自身のvalueプロパティにアクセスするためにselfキーワードを使用しています。
struct SomeStruct {
let value = 123
func printValue() {
print(self.value)
}
}
インスタンスそのものではなく、インスタンスのプロパティやメソッドにアクセスする場合、selfキーワードを省略できます。たとえばself.プロパティ名のようなプロパティへのアクセスは、単にプロパティ名に置き換えられます。次の例では、上記の例のself.valueをvalueに置き換えています。
struct SomeStruct {
let value = 123
func printValue() {
print(value)
}
}
実行できるソースコード
Playgrandで実行できるようになっております。
クラスについて
クラスは参照型で、継承をサポートしています。クラスは一つ以上のスーパークラスを持つことができ、そのスーパークラスの特性を引き継ぐことができます。
// クラスの定義
class SampleClass {
var name: String
var age: Int
// 初期化メソッド
init(name: String, age: Int) {
self.name = name
self.age = age
}
}
// クラスのインスタンス化
var sampleClass = SampleClass(name: "John", age: 20)
// クラスのプロパティにアクセス
print(sampleClass.name) // "John"が出力される
print(sampleClass.age) // 20が出力される
構造体について
構造体は値型で、継承をサポートしていません。構造体はプロパティとメソッドを持つことができます。
import UIKit
// Structの定義
struct SampleStruct {
var name: String
var age: Int
}
// Structのインスタンス化
var sample = SampleStruct(name: "John", age: 20)
// Structのプロパティにアクセス
print(sample.name) // "John"が出力される
print(sample.age) // 20が出力される
列挙型
列挙型は値型で、継承をサポートしていません。列挙型は特定の範囲の値を表すことができ、それぞれの値はケースと呼ばれます。
import UIKit
// Structの定義
struct SampleStruct {
var name: String
var age: Int
}
// Structのインスタンス化
var sample = SampleStruct(name: "John", age: 20)
// Structのプロパティにアクセス
print(sample.name) // "John"が出力される
print(sample.age) // 20が出力される
イニシャライザ
イニシャライザは、クラス、構造体、または列挙型の新しいインスタンスを作成するための特別なメソッドです。イニシャライザは、インスタンスの初期設定を行い、それぞれのストレージプロパティに適切な初期値を設定します。
struct SampleStruct {
var name: String
var age: Int
init(name: String, age: Int) {
self.name = name
self.age = age
}
}
staticの使用例
staticは、インスタンスではなく型自体に関連付けられたプロパティまたはメソッドを定義します。これは、その型のすべてのインスタンスで共有されます。
struct SampleStruct {
static var sharedProperty = "Shared Property"
static func sharedMethod() {
print("This is a shared method.")
}
}
print(SampleStruct.sharedProperty) // "Shared Property"が出力される
SampleStruct.sharedMethod() // "This is a shared method."が出力される
ストアドプロパティ
ストアドプロパティは、特定のクラス、構造体、または列挙型のインスタンスに関連付けられた値を保持します。これらのプロパティは、値を「格納」するため、ストアドプロパティと呼ばれます。以下に、ストアドプロパティの使用例を示します。
もっとわかりやすく言うと、値を保持するプロパティと表現されます。
struct SampleStruct {
var name: String // ストアドプロパティ
var age: Int // ストアドプロパティ
}
var sample = SampleStruct(name: "John", age: 20)
print(sample.name) // "John"が出力される
print(sample.age) // 20が出力される
struct SampleStruct {
var name: String {
willSet(newName) {
print("The name is about to change to \(newName).")
}
didSet(oldName) {
print("The name has just changed from \(oldName) to \(name).")
}
}
var age: Int
}
var sample = SampleStruct(name: "John", age: 20)
sample.name = "Jane" // "The name is about to change to Jane."と"The name has just changed from John to Jane."が出力される
プロパティオブザーバ
プロパティオブザーバは、プロパティの値が変更される前後にカスタムアクションを実行するための機能です。willSet
は値が設定される前に呼び出され、didSet
は新しい値が設定された後に呼び出されます。
struct SampleStruct {
var name: String {
willSet(newName) {
print("The name is about to change to \(newName).")
}
didSet(oldName) {
print("The name has just changed from \(oldName) to \(name).")
}
}
var age: Int
}
var sample = SampleStruct(name: "John", age: 20)
sample.name = "Jane" // "The name is about to change to Jane."と"The name has just changed from John to Jane."が出力される
レイジーストアドプロパティ
レイジーストアドプロパティは、そのプロパティが初めてアクセスされるまで初期化が遅延されるプロパティです。lazy
キーワードを使用して定義します。
struct SampleStruct {
lazy var expensiveOperationResult: String = {
print("Performing expensive operation...")
// ここで高コストの操作を行う
return "Result of expensive operation"
}()
}
var sample = SampleStruct()
print(sample.expensiveOperationResult) // "Performing expensive operation..."と"Result of expensive operation"が出力される
コンピューテッドプロパティ
コンピューテッドプロパティは、値を格納するのではなく、計算によって値を生成するプロパティです。get
とset
キーワードを使用して定義します。
解説
プロパティ名: 型名 {
get {
return文によって値を返す処理
}
set {
値を更新する処理
プロパティに代入された値には定数newValueとしてアクセスできる
}
}
使用例
struct SampleStruct {
var name: String
var age: Int
var description: String {
get {
return "\(name) is \(age) years old."
}
set(newDescription) {
// 新しい説明を解析して、nameとageを更新する
}
}
}
var sample = SampleStruct(name: "John", age: 20)
print(sample.description) // "John is 20 years old."が出力される
ゲッターについて
get
(ゲッタ)は、ほかのストアドプロパティなどから、値を取得して、コンピューテッドプロパティの値として返す処理です。値を返すときは、return
を使います。
セッター
set
(セッタ)は、プロパティに代入された値を使用して、他のプロパティなどを更新する処理です。
セッタ内では、暗黙的に宣言されたnewValueという定数を通じて代入された値にアクセスできます。
最後に
Dartを普段書いているのですが、Swiftの学習もまたしてみたいと思い久しぶりに記事を書いてみました。Dartよりもコードやライフサイクルが独特なので、覚えるの大変です😅