初めに
この記事は、プロパティの分類・get/setなど基礎的な箇所が理解と感じていたため、自分なりに簡単いまとめてました。
間違えている箇所や、こっちの説明の方が分かりやすくなるよなどのアドバイスがありましたら、コメントに書いていただけると幸いです。
コード
import Foundation
// カスタムな型とプロパティの分類
// カスタムな型
// ユーザークラス
class User {
// インスタンスプロパティ
let ID: Int
var name: String
var age: Int
var type: UserType
// プロパティを持った型を使用するにはインスタンス化が必要
// 型名(イニシャライザで指定した引数)
init(ID: Int, name: String, age: Int) {
// self.IDはインスタンスプロパティのlet ID: Intを、= IDはイニシャライザの引数ID: Intを指している。
// プロパティ名と引数名が同じ場合はどちらを指しているのかがわからないため明示的にselfを付ける必要がある。
self.ID = ID
self.name = name
self.age = age
self.type = UserType()
}
// メソッド
func selfIntroduction() {
var str = "初めましてこんにちは\n"
str += "私は\(self.name)と申します。\n"
str += "以後ご承知おきください"
print(str)
}
func userData() {
// ここで書いているID, name, age, typeはインスタンスプロパティを指している。
var str = "ID:\(ID)\n名前:\(name)\n"
str += "年齢:\(age)\nユーザータイプ:\(type)"
print(str)
}
}
// ユーザータイプ列挙型
enum UserType {
case guest
case host
case owner
// タイププロパティ
static let guide = "これはユーザーのタイプを扱う型です"
// イニシャライザ
init() {
self = .guest
}
// メソッド
// タイププロパティは型名.プロパティ名でアクセス
func printGuide() {
print(UserType.guide)
}
}
// インスタンス化
let user = User(ID: 39, name: "中村", age: 25)
// インスタンスプロパティはインスタンス名.プロパティ名でアクセス
print(user.name)
// 中村
user.selfIntroduction()
/*
初めましてこんにちは
私は中村と申します。
以後お見知り置きを
*/
user.userData()
/*
ID:39
名前:中村
年齢:25
*/
// 値を格納する格納プロパティ, 値を格納せずに計算にのみを行う計算(コンピューテッド)プロパティがある。
/* プロパティの分類は4つに分けられる
・ ストアドインススタンスプロパティ = インスタンスに紐づく格納プロパティ
・ ストアドタイププロパティ = 型に紐づく格納プロパティ
・ コンピューテッドインスタンスプロパティ = インスタンスに紐づく計算プロパティ
・ コンピューテッドタイププロパティ = 型に紐づく計算プロパティ
*/
// 球の表面積、体積を求めるクラス
class Sphere {
// ストアドタイププロパティ
static let info = "これは球体を便利に扱うクラスです"
// ストアドインスタンスプロパティ
var radius: Double// 半径
// イニシャライザ
// 今回はradiusがどの変数のことかが自明ためselfを省略できる。
init(r: Double) {
radius = r
}
// コンピューテッドインスタンスプロパティ
// 球の表面積
var area: Double {
// プロパティにアクセスするとgetが動く
get {
// 戻り値
return 4 * Double.pi * radius * radius
}
// プロパティに値を代入すると動く
set(p) {
radius = sqrt(p / (4 * Double.pi))
}
}
// コンピューテッドインスタンスプロパティ
// 球の体積
var volume: Double {
get {
return 4 / 3 * Double.pi * radius * radius * radius
}
set(p) {
radius = pow(3 * p / (4 * Double.pi), 1 / 3)
}
}
// コンピューテッドタイププロパティ
// Unit = 単位 = 1
static var unit: Sphere {
// getのみは可だが、setのみは不可(get,set両方必要)
get {
return Sphere(r: 1.0)
}
}
// コンピューテッドプロパティは、
// ゲッタのみの場合getを省略可能 ←実用上重要
// 処理が1行の場合returnが省略可能 ←実用上重要
// 半径が0の球
static var zero: Sphere {
Sphere(r: 0.0)
}
}
// コンピューテッドインスタンスプロパティの使い方
// インスタンス化
let s = Sphere(r: 10)
// 半径10の球の表面積
// Shpere構造体のareaのget{}が動く
var value = s.area
print("表面積は: \(value)")
// 表面積は: 1256.6370614359173
// 表面積から半径を決める
print("変更前: \(s.radius)")// 変更前: 10.0
// Shpere構造体のareaのパラメータpに100が代入され、set{}が動く
s.area = 100
print("変更後: \(s.radius)")// 変更後: 2.8209479177387813
// コンピューテッドタイププロパティの使い方
let t = Sphere.unit
// 型名.プロパティ名でアクセス
print("半径1の球の表面積は\(t.area)")// 半径1の球の表面積は12.566370614359172
print("半径1の球の体積は\(t.volume)")// 半径1の球の体積は4.1887902047863905
// 型が決まっていると型名の省略ができる ←実用上重要
let u: Sphere
u = .zero
// 1行で書くとこうなる
let w: Sphere = .zero
// こんな使い方ができる
// sという引数はSphere型なので、printInfoメソッドを呼び出すときには型名を省略することが出来る。
func printInfo(s: Sphere) {
var str = "球の情報を出力します\n"
str += "半径:\(s.radius)\n"
str += "表面積:\(s.area)\n"
str += "体積:\(s.volume)\n"
print(str)
}
// 型が決まっているので型名を省略して .プロパティ名でアクセス出来る。
// 列挙型と同じ仕組み
printInfo(s: .unit)
printInfo(s: .zero)
まとめ
プロパティの分類とget/setを使う意味がわからなかったのですが、少し理解できたような気がします。
自分のアプリで使うにはまだまだ理解できていないので、今後も手を動かして使いながら訓練していきたいと思います。
参考文献
Swiftの学習を始めた初学者が、まず最初に見た方が良いYouTubeチャンネルかなと思っています。
Swiftの基礎文法などを、初学者でも分かるようにホワイトボードとPlaygroundeを使用して解説しているので、本やドキュメンントだけではなかなか理解出来ないという人がいましたら、ぜひ見てみてください。
そういうことだったのか!とすんなり理解できるか事が多いかと思いますのでおすすめです。
the swift programming language swift 5.7の日本語版ドキュメントです。
英語が読めないので、翻訳の精度が良いのかどうかは分からないのですが、サンプルコードが多く載っているため、手を動かしながら学習する事が出来るのでおすすめです。