プロパティの(価)値
前回予告したとおり、
しかしそもそも
iOSの辞書によると

値の中の値
それではSwiftにおけるプロパティとはいったいなんでしょうか? 断言する前に実例を見てみましょう。Playgroundで次を入力してみてください。
"swift".description // "swift"
(42).description // "42"
(42.195).description // "42.195"
[42].description // "[42]"
["swift":4.1].description
// "["swift": 4.0999999999999996]"
それぞれの値を文字列にしたものが""
に囲まれて表示されているはずです。これがそれぞれの値.description
という名のプロパティ
今度は.description
を.hashValue
にしてみましょう。String
やInt
やDouble
ではこのようにInt
の値が出てきますが……、
"swift".hashValue // 4799434080856491603 (42).hashValue // 42 (42.195).hashValue // 4631135235630652457
Array
やDictionary
だとエラーになります
[42].hashValue // error: value of type '[Int]' has no member 'hashValue' ["swift":4.1].hashValue // error: value of type '[String : Double]' has no member 'hashValue'
どんな値がどんなプロパティを持つかは、
今そこにあるプロパティ・その場で作られるプロパティ
プロパティは型によって決まる。具体的にその様子を見てみましょう。
struct Point<T:FloatingPoint> {
var x:T
var y:T
}
Point
というStruct
を作ったうえで使ってみます。
var dp = Point(x:3,y:4) dp.x // 3 dp.y // 4
.x
と.y
というプロパティが存在し、
このPoint
に原点.distance
というプロパティを付け加えてみましょう。
import Darwin // for sqrt()
extension Point {
var distance:T {
return sqrt(x*x + y*y)
}
}
実行結果は次のとおり。
dp.distance // 5
メモリにそのまま保持されているストアド・
「あれ? これってメソッド
extension Point {
func getDistance() -> T {
return sqrt(x*x + y*y)
}
}
dp.getDistance() // 5
ここで.getDistance()
の()
を取ってみましょう。エラーにはならず、() -> Double
と出てくるはずです。
そうなのです。Swiftではメソッドもまた単なる関数型のストアド・()
を付けずに実行されるメソッドにすぎないのです。
しかし、
.distance
の定義を次のように変えてみます。
extension Point {
var distance:T {
get {
return sqrt(x*x + y*y)
}
set {
let d = distance
x *= newValue / d
y *= newValue / d
}
}
}
すると……、
dp.distance = 10 dp.x // 6 dp.y // 8
これは、
extension Point {
func getDistance() -> T {
return sqrt(x*x + y*y)
}
mutating func setDistance(_ newValue:T) {
let d = self.getDistance()
x *= newValue / d
y *= newValue / d
}
}
ほかの言語でも、()
の有無に過ぎず、
添字もsubscriptという名のプロパティ
配列
[42][0] // 0 ["swift":4.1]["swift"] // 4.1
しかしよく考えてみると、
例として、Int
をBool
の配列として操作できるようにしてみます。
extension Int {
subscript(_ i:Int)->Bool {
get {
return self & (1 << i) == 0
}
set {
var mask = 1 << i
if !newValue {
mask = ~mask
self &= mask
} else {
self |= mask
}
}
}
}
実行してみます。
var v = 0; v[1] = true // v = 000010 == 2 v[3] = true // v = 001010 == 10 v[5] = true // v = 101010 == 42 v // 42
Swiftではsubscript
というメソッド=プロパティを定義することによって、
ちなみに と書くことはできません。エラーになるべきなのですが、 Rubyではクラス自体もオブジェクトですが、 こうしてみると、 1つは、 当然ながら、 もう1つは、 何でも入るかわりにそのままでは何もできません。何もできないように組込みプロパティが存在しないだけではなく、 そして最後に総称型 を と書き直すことはできません。別の言い方をすると、 値があるところにプロパティがあり、 (ほぼ) 次回もまた、 2022年8月18日発売subscript
というのはSwiftではキーワード扱いなので、[42].subscript(0)
% swift
Welcome to Apple Swift version 4.0.3 (swiftlang-900.0.74.1 clang-900.0.39.2). Type :help for assistance.
1> [42].subscript(0)
Segmentation fault
型もまた値。そして値には……
.self
というプロパティを使います。type(of:42) == Int.self // true
type(of:42.0) == Int.self // false
何でもはできないわよ。できることだけ
Optional
。var v:Int? = nil
v.hashValue // error: value of optional type
'Int?' not unwrapped;
?
か!
でunwrapせねばならず、Optional
ではありません。Optional
の存在意義を考えれば、Any
。extension Any { // error: non-nominal type 'Any'
cannot be extended
}
extension
することも禁止されています。使うときにはasなどで中身を取り出すという意味で、Optional
と同様に自然です。func id<T>(_ x:T)->T {
return x
}
let idd<T>:(T)->T = { return $0 }
[42]
の型はArray
ではなくArray<Int>
であり、["swift":4.
の型はDictionary
ではなくDictionary<String,Double>
であることを考えれば、まとめ
Any
およびOptional
、.subscript
という名のメソッドは禁則事項本誌最新号をチェック!
Software Design 2022年9月号
B5判/
定価1,342円
MySQL アプリ開発者の必修5科目
不意なトラブルに困らないためのRDB基礎知識
OSSソースコードリーディングのススメ
企業のシステムを支えるOSとエコシステムの全貌
今さら聞けないSSH
MySQLで学ぶ文字コード
新生