詳解Swift(6)〜パターン

2016. 07. 04
(※2016年7月4日追記:この記事は詳解 Swift(初版第1刷)を元に、Xcode 7.3.1(Swift 2.2)下における加筆・修正を行っています。(Xcode 7.3からXcode 7.3.1での変更点はありませんが、「列挙型の付加情報を書き換えるメソッドとプロパティ」など若干追記しています))



CHAPTER 06 パターン



●6.1 タプル


・タプルの概要

本書ではタプル同士の比較はできないとありますが、「卵は世界である/Swift 2.2の変更点をまとめてみた」で指摘されているようにSwift 2.2 から条件付きでできるようになりました。

(1, 2) == (1, 2)    // true

これに関しては「Swift.org/New Features in Swift 2.2」の「Tuple comparison is built-in」で説明されています。

タプルの比較の導入

タプルはSwiftの基本的なデータ型であり、(特に関数は複数の値を返すことができないために)多くの利点をもたらします。
Swift 2.2 では 2 つのタプルの等価性を比較する機能を導入しており、これはあるタプルの各要素に対して他方の要素が一致するかを調べることを意味し、全ての要素が一致する場合は true を返します。

例えば以下のコードは "No match" を出力します。

let singer = (first: "Taylor", last: "Swift")
let alien = (first: "Justin", last: "Bieber")

if singer == alien {
    print("They match! That explains why you never see them together…")
} else {
    print("No match.")
}

Swift 2.2 ではタプルに含まれる要素が 6 より多くない場合、すなわちタプルの比較は 6 項まで動作します。

注:Swift 2.2 で等価性を調べる時には要素名は無視されるので、以下のコードの singer と bird は等しいとみなされます。

let singer = (first: "Taylor", last: "Swift")
let bird = (name: "Taylor", breed: "Swift")

if singer == bird {
    print("This explains why she sings so well.")
} else {
    print("No match.")
}

この変更の詳細については「
Swift Evolution proposal」を参照してください。」


・キーワード付きのタプルと代入

本書では異なるキーワードでも型と要素数が同じであれば互いにキャストできるとありますが、現在は異なるキーワード間ではキャストできないようです。

v3 = photo as (image:String, x:Int, y:Int)        // error: '(file: String, width: Int, height: Int)' is not convertible to '(image: String, x: Int, y: Int)'; did you mean to use 'as!' to force downcast?

v3 = photo as (String, Int, Int)    // ("tiger.jpg", 640, 800)

キーワード無しへの変換は正常に動作します。
この場合でも変数 v3 のキーワード (image:String, x:Int, y:Int) は活きたままで、キーワード無しになるわけではありません。


・タプルをswitch文で使う

本書ではswitch文でキーワード付きタプルを使ってもキーワードは無視されるとありますが、現在はキーワードを確認しているらしく、対象となる式と case 節のキーワードが異なる場合はエラーになります。

var rect = (width:10, height:28)
switch rect {
case (month: 10, day: let d): print("10月\(d)日")    // error: tuple pattern element label 'month' must be 'width'
case (width: _, height: let h): print("高さ=\(h)")
default: break        // Default will never be executed
}

余談ですが、一つ目の case 節の条件をキーワード無しの (10, let d) などとしてエラーが出ないようにした場合、2つ目の case 節が全ての条件を満たしているため default 節が実行されないとの警告が出ます。



●6.2 列挙型


・共有型の列挙型

Ticket 型の中で使用している日付を表す Date 型は、「SBクリエイティブ:詳解 Swift サンプルダウンロード」では3つの Int 型によるタプルに typealias で別名を付けて使用しています。

typealias Date = (Int, Int, Int)

また for-in 文で使用している List は、myticket、pass、elders、mycard(そして本文中には無い変数 card2)を含む Ticket 型の配列です。

var card2 = Ticket.カード(30, 小人:true)

var list = [ myticket, pass, elders, mycard, card2 ]



・列挙型の付加情報を書き換えるメソッドとプロパティ

List6-8 の実行例ですが、本文を読んだだけでは理解できません。

var mycard = Ticket.切符(300, 小人: false)
if tt.pay(260) { print("OK") }

まず1行目の変数 mycard ですが、"切符" ならば (Int, Date, 小人:Bool) のタプルのはずであり、前項 List6-7 の実行例で "切符" の定数は myticket、"カード" の変数を mycard としていること、付加情報が (Int, 小人:Bool) のタプルであることから "カード" の変数だと推測できます。
しかし2行目の tt はTicket 型の定数か変数であることしか分かりません。

そこで「SBクリエイティブ/詳解 Swift サンプルダウンロード」を確認してみると、やはり mycard は ”カード” の変数であり、Ticket 型配列 List から for-in 文で取り出した定数 t を変数に入れ替えたものが tt であることが分かりました。

var today = (2014, 10, 26)

let myticket = Ticket.切符(250, today, 小人: false)
let pass = Ticket.一日券(today, 小人: true)
let elders = Ticket.敬老パス        // ここまではList6-7の実行例と同じ
let mycard = Ticket.カード(300, 小人: false)        // List6-7の実行例とは残高が異なる
var card2 = Ticket.カード(30, 小人: true)        // 本文に記載なし

var list = [ myticket, pass, elders, mycard, card2 ]        // 本文に記載なし

for t in list {
    switch t {
    case let .切符(fare, _, flag): print("普通券: \(fare) " + (flag ? "小人" : "大人"))
    case .一日券: print("一日券")
    case .敬老パス: print("敬老パス")
    case .カード(let r, true) where r < 110: print("カード: 残額不足")
    case .カード(let r, false) where r < 230: print("カード: 残額不足")
    case .カード: print("カード")
    }
    var tt = t        // 書き換えメソッド pay を呼び出すため定数 t を変数 tt に
    if tt.pay(260) { print("OK") }        // 運賃260円の場合の可否を出力
    else { print("OUT") }
    switch tt {
        // カードの残高を出力
    case .カード(let p, _): print("\(p)")
    default: break
    }

}

実行結果は次の通りです。

普通券: 250 大人        // myticket
OUT
一日券        // pass
OK
敬老パス        // elders
OK
カード        // mycard
OK
40
カード: 残高不足        // card2
OUT
30        // 残高不足の場合、情報の書き換え(運賃の引き去り)は起こらない

サンプルにもプロパティ isChild を使用している形跡がありませんし、紆余曲折があったのかもしれません。


・共用型の列挙型と構造体を組み合わせる

イニシャライザ内で90日後の日付を得るために使用している dateAfter() 関数は本文中に記載されておらず、「SBクリエイティブ/詳解 Swift サンプルダウンロード」を確認したところ実際に何日後の日付を計算しているわけではなく単に引数の日付を返すだけの便宜上のものでした。

typealias Date = (Int,Int,Int)
func dateAfter(days:Int, date:Date) -> Date {
    return date
}

しかし本文中では「日付.dateAfter(90)」と Date 型の関数として記述しているのに対し、サンプルコードではルートに dateAfter() 関数が記述されている上に、Date 型は構造体ではなく Int 型3つのタプルの変名として宣言されているので、Date を構造体にし dateAfter() 関数をそのメソッドとする必要があります。

また本文中では何日後を表す整数1つのみを引数とし、サンプルコードでは現在の日付を表す Date 型も引数としていますが、Date 型構造体のメソッドであるなら自身を引数として取る必要はないので日数だけで十分だと思われます。

エラーなくコードを通すためだけなら以下のような記述で十分でしょう。

struct Date {
    var year, month, day: Int
    func dateAfter(days:Int) -> Date {
        // 経過日数の加算処理
        return self
    }
}

これに伴い変数 today も Date 型構造体に書き換える必要があります。

var today = (2014,10,26)        // タプル
var today = Date(year: 2014, month: 10, day: 26)        // 構造体



卵は世界である/Swift 2.2の変更点をまとめてみた

Swift.org/New Features in Swift 2.2

Wikipedia/フィボナッチ数

SBクリエイティブ/詳解 Swift サンプルダウンロード

詳解 Swift 改訂版(Amazon)
 






bose_soundlink_revolve
0 Comments
Leave a comment
管理者にだけ表示を許可する
Top
0 Trackbacks
Top
Calendar
03 | 2017/04 | 05
Sun Mon Tue Wed Thu Fri Sat
- - - - - - 1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
30 - - - - - -
Recent Articles
iTunes


Swift
Categories
Tips
Profile

水月杏香

Author:水月杏香
永遠の初心者プログラマ。

Wish List
WACOM


ARC
Technical Q&A
情報プロパティリストキー
Start Developing iOS Apps Today
BOSE

bose_soundlink_revolve
Reference
NSApplicationDelegateプロトコル
NSArrayクラス
NSAutoreleasePoolクラス
NSBundleクラス
NSBundle UIKit追加分
NSCalendarクラス
NSCoderクラス
NSCodingプロトコル
NSCopyingプロトコル
NSDataクラス
NSDateクラス
NSDateFormatterクラス
NSDictionaryクラス
NSEntityDescriptionクラス
NSEnumeratorクラス
NSErrorクラス
NSExceptionクラス
NSFetchRequestクラス
NSFileHandleクラス
NSFileManagerクラス
NSIndexPathクラス
NSIndexPath UIKit追加分
NSKeyedArchiverクラス
NSKeyedUnarchiverクラス
NSKeyValueCodingプロトコル
NSLocaleクラス
NSManagedObjectクラス
NSManagedObjectContextクラス
NSManagedObjectModelクラス
NSMutableArrayクラス
NSMutableCopyingプロトコル
NSMutableDictionaryクラス
NSMutableSetクラス
NSNotificationクラス
NSNotificationCenterクラス
NSNullクラス
NSNumberクラス
NSObjectクラス
NSObject UIKit追加分
NSObjectプロトコル
NSPersistentStoreクラス
NSPersistentStoreCoordinatorクラス
NSPredicateクラス
NSPropertyListSerializationクラス
NSRunLoopクラス
NSSetクラス
NSStringクラス
NSString UIKit追加分
NSTimerクラス
NSTimeZoneクラス
NSURLクラス
NSURLProtectionSpaceクラス
NSURLRequestクラス
NSUserDefaultsクラス
NSValueクラス

UIActionSheetクラス
UIActionSheetDelegateプロトコル
UIActivityIndicatorViewクラス
UIAlertViewクラス
UIAlertViewDelegateプロトコル
UIApplicationクラス
UIApplicationDelegateプロトコル
UIBarButtonItemクラス
UIBarItemクラス
UIButtonクラス
UIColorクラス
UIControlクラス
UIDatePickerクラス
UIDeviceクラス
UIEventクラス
UIFontクラス
UIGestureRecognizerクラス
UIImageクラス
UIImageViewクラス
UIKit Function
UILabelクラス
UINavigationControllerクラス
UINavigationItemクラス
UIPickerViewクラス
UIPickerViewDataSourceプロトコル
UIPickerViewDelegateプロトコル
UIPinchGestureRecognizerクラス
UIResponderクラス
UIScreenクラス
UIScrollViewクラス
UISearchBarクラス
UISearchBarDelegateプロトコル
UISegmentedControlクラス
UISliderクラス
UISwipeGestureRecognizerクラス
UISwitchクラス
UITableViewクラス
UITableViewCellクラス
UITableViewControllerクラス
UITableViewDataSourceプロトコル
UITableViewDelegateプロトコル
UITapGestureRecognizerクラス
UITextFieldクラス
UITextFieldDelegateプロトコル
UITextInputTraitsプロトコル
UITextViewクラス
UITextViewDelegateプロトコル
UIToolbarクラス
UITouchクラス
UIViewクラス
UIViewControllerクラス
UIWebViewクラス
UIWebViewDelegateプロトコル
UIWindowクラス

AVAudioPlayerクラス
AVAudioPlayerDelegateプロトコル

CADisplayLinkクラス
CAEAGLLayerクラス
CALayerクラス

CGAffineTransform
CGBitmapContext
CGColor
CGColorSpace
CGContext
CGGeometry
CGImage
CGPath

EAGLContextクラス
EAGLDrawableプロトコル

Foundation Constants
Foundation Data Types
Foundation Functions

MPMediaItemクラス
MPMediaItemArtworkクラス
MPMediaPlaylistクラス
MPMediaPropertyPredicateクラス
MPMediaQueryクラス
MPMusicPlayerControllerクラス

Randomization Services

System Sound Services
Amazon


OpenGL ES
SQLite
Monthly Archives
Recent Comments
Recent TrackBacks
RSS Link
Visitors
QR Code
QR