【Swift】基礎文法まとめ(後編)

プログラミング初心者の勉強ブログ #134

Swift基礎文法後編。値型と参照型の違いや、構造体(struct)、列挙型(enum)、ジェネリクス、subscript、guard、Optional Chainingなど。基礎と言いながら応用的な内容を含んでいる。enumよくわからん。とりあえずうやむやだったSwift文法は一通り整理できそう。

※前編は【Swift】基礎文法まとめ(前編)にて。

※中編は【Swift】基本文法まとめ(中編)にて。

 

目次

[toc]

 

値型と参照型

// Int, Double, Array .. -> 値型
// Class -> 参照型
// 値型と参照型で再代入したときの挙動が異なる


// 値型の場合
var original = 10
var copy = original // originalの値そのもの
original = 20
print(original) // 20
print(copy) // 10



class User {
    var name: String
    init(_ name: String) {
        self.name = name
    }
}

// 参照型の場合
var original = User("tom")
var copy = original // originalが格納されている場所
original.name = "bob"
print(original.name) // "bob"
print(copy.name) // "bob"

 

構造体(struct)

// 構造体
// - クラスとほぼ同機能
// - 値型
// - 継承ができない
// - extension, protocolは使える
// 基本的に一回作ったら値が変わってほしくないようなデータに使用

//class User {
struct User {
    var name: String
    init(_ name: String) {
        self.name = name
    }
	
    // 本来構造体では値の変更ができない
    // 明示的にmutatingを用いると値の変更が可能
    mutating func changeName() {
        self.name = name.uppercased()
    }
}

var original = User("tom")
var copy = original // copy: originalの値
original.name = "bob"
print(original.name) // bob
print(copy.name) // tom

 

列挙型(enum)

// 関連する値をまとめて型にする
// 列挙型は値型

// enumちょっとよくわからん、まだ勉強が必要

enum Direction {
    case right
    case left
}

var dir: Direction.right

switch (dir) {
case .right:
    print("right")
case .left:
    print("left")
}

enum Direction: Int {
    case right = 1
    case left = -1
}

print(Direction.right.rawValue)

 

ジェネリクス

// 汎用化されたデータ型

// TはTypeのT

//func getThree(x: Int) {
func getThree<T>(x: T) {
    print(x)
    print(x)
    print(x)
}

// Int型だけでなく、どの型が引数に与えられても対応できる
getThree(x: 5)
getThree(x: "hello")
getThree(x: 2.3)

 

subscript

// クラス、構造体、列挙型などにインデックスをつけられる

class Team {
    var members = ["aaa", "bbb", "ccc"]
	
    // インスタンスにインデックスが付与されていた時反応
    subscript(index: Int) -> String {
        get {
            return members[index]
        }
        set {
            members.insert(newValue, at: index)
        }
    }
}

var giants = Team()
print(giants[1]) // bbb
giants[3] = "ddd"
print(giants[3]) // ddd

 

guard文

// 異常処理をわかりやすく書くための仕組み

// if letで書く場合
func sayHi(_ msg: String?) {
    if let s = msg {
        print(s)
    } else {
        print("value not set!")
    }
}

// early returnの場合
func sayHi(_ msg: String?) {
    if msg == nil {
        print("value not set!")
        return
    }
    print(msg!)
}

// guardで書く場合
func sayHi(_ msg: String?) {
    guard let s = msg else {
        print("value not set!")
        return
    }
    print(s)
}

sayHi(nil)
sayHi("hello")

 

例外処理

// 列挙型でエラーパターンを定義
enum LoginError: Error {
    case emptyName
    case shortName
}

class User {
    let name: String
    init(_ name: String) {
        self.name = name
    }
	
    // 例外発生の可能性がある場合、throwsを使う
    func login() throws {
        guard name != "" else {
            throw LoginError.emptyName
        }
        guard name.count > 5 else {
            throw LoginError.shortName
        }
        print("login success")
    }
}

let tom = User("tom")
let tom = User("takahashi")
let tom = User("")

// do catchでエラー表示
do {
    try tom.login()
} catch LoginError.emptyName {
    print("please enter your name")
} catch LoginError.shortName {
    print("too short")
}

 

Optional Chaining

// オプショナル型のnilチェックをスッキリ書くためのもの
// 変数が nil だったら nil を、そうではなかったらその値を含む Optional 型を返す
// nilだった場合も、単に返り値がnilになるだけでエラーにならない

// 非オプショナル型の場合...
//class User {
//    var name: String = ""
//}
//
//let user: User()
//user.name = "him"
//let s = user.name.uppercased()
//print(s)

// オプショナル型の場合
class User {
    // optional宣言の省略型
    var name: String? = ""
}

// optional宣言の省略型
var user: User?
user = User()

// Optional Chaining(後ろに?をつける)
user?.name = "him"
if let s = user?.name?.uppercased() {
    print(s)
}

 

暗黙的 unwrap optional

// Implicitly Unwrapped Optional
// 宣言で「!」をつけることで、値を使う時にUnwrapしなくてもいいOptional型だと理解する

// 通常のoptional型定義(後ろに?)
//var msg: String?

// Implicitly Unwrapped Optional(後ろに!)
var msg: String!
msg = "hello"

// 本来ならunwrap処理が必要であるが、
//if msg != nil {
//    print(msg!)
//}

// この場合はunwrap不要で利用できる
print(msg)

 

※前編は【Swift】基礎文法まとめ(前編)から。

※中編は【Swift】基本文法まとめ(中編)から。

 

 

まとめ

オプショナル型についてはだんだんと理解できてきた気がする。しょっちゅう出てくる?と!に嫌悪感を抱いていたが、克服できるかもしれない。オプショナル型含め、structとprotocolとenumはSwiftで初めて知った概念。言語の違いっていうのは、書き方と使用できる型と制約具合なのかな。forとかifとか配列とか、どの言語でも必ず出てくる。言語もやればやるほど学習コストは確実に減っていく。既存の知識から「あれでいうあれは、これでいうこれね」と当てはめるパターンのやつ。「classを型として扱う」っていうのが良い(今まで考えてこなかったが、どの言語もそうだったのかね、わからん)。とりあえず3本書いたので満足。

以上ありがとうございました。

返信を残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です

CAPTCHA