swiftの基本的な話
swiftの学習を始めたため、アウトプットを兼ねて基礎的な部分についてまとめて学習したことを投稿
変数と定数
変数
あとから値を変更できる
//var 変数名 = 値で入力
var a = 100
print(a) //=> 100
a = 200
print(a) //=> 200
定数
あとから値を変更できない
//let 変数名 = 値で入力
let a = 100
print(a) //=> 100
a = 200 //=> Cannot assign to value: 'a' is a 'let' constant
型の宣言について
変数名の後に型の宣言を行うことが出来る。
//int型(整数)の場合
var a: Int = 123
//double型(浮動小数点)の場合
var a: Double = 123.2
//string型(文字列)の場合
var a: String = "Hello"
また、型を指定しない場合は、判定してくれる「型推論機能」がある
var a = 123 //=> int型
var a = 123.2 //=> double型
var a = "Hello" //=> string型
また型の後に?をつけるとオプショナル型となる
通常の変数と異なり空の値(値が無い)状態を保持することができる変数。
var a: Int?
print(a) //=> nil
a = 456
print(a) //=> Optional(456)
a = nil
print(a) //=> nil
オプショナル型を他の変数や定数と合わせて使う場合、
オプショナル型の変数の値がnilでないことを明示するためにアンラップする必要がある。
let a = 1
//型の後に?をつけてアンラップを行う
var b: Int? = 7
let c = a + b!
print(f) //=> 8
四則演算
以下のように四則演算が出来る
let a = 5
let b = 4
//足し算
let c = a + b
print(c) //=> 9
//引き算
let d = a - b
print(d) //=> 1
//掛け算
let e = a * b
print(e) //=> 20
//割り算
let f = a / b
print(f) //=> 1
//割り算の余り
let g = a % b
print(g) //=> 1
//小数点の場合は以下のような計算になる
let h = 2.5
let i = 1.5
let j = h / i
print(j) //=> 1.66666666...
文字式と数値を組み合わせる
let a = "Hello "
let b = "World!"
let c = a + b
print(c) //=> Hello World!
let d = "私は"
let e = "歳です"
let f = 20
//"\()"で数字を文字列に変換
let g = d + "\(f)" + e
print(g) //=> 私は20歳です
比較演算
true falseでの判定を行うことが出来る
let a = 3
let b = 5
// a と b が等しいか
let c = a == b //cの値はBool値となる
print(c) //=> false
// aはbと等しく無いか
let d = a != b
print(d) //=> true
// aはbよりも大きいか
let e = a > b
print(e) //=> false
// aはbよりも小さいか
let f = a < b
print(f) //=>true
// aは3以上か
let g = a >= 3
print(g) //=>true
// aは2以下か
let h = a <= 2
print(h) //=>false
// aは2より大きく、かつ7未満か
let i = a > 2 && b < 7
print(i) //=> true
// aは2より小さい、またはbが4より大きい
let j = a < 2 || b > 4
print(j) //=> true
条件分岐
if、else if、elseを用いて条件分岐をすることが出来る
let a = true
if a {
print("hello")
} else {
print("Hi!")
}
//=> hello
let time = 15
if time < 12 {
print("Good morning!")
} else if time < 18 {
print("Good aftermoon!")
} else {
print("Good night!")
}
//=> Good aftermoon!
time = 11 //=> Good morning!
time = 19 //=> Good night!
配列
//: [Int]は省略も出来る
let a: [Int] = [1, 2, 3, 4, 5]
let b = a[0]
let c = a[2]
let d = a[4]
print(b) //=> 1
print(c) //=> 3
print(d) //=> 5
var e = [1, 2, 3, 4, 5]
//6を配列に追加
e.append(6)
print(e) //=> [1, 2, 3, 4, 5, 6]
//値の変更、3番目を9に変更
e[2] = 9
print(e) //=> [1, 2, 9, 4, 5, 6]
//値の削除、4番目を削除
e.remove(at: 3)
print(e) //=> [1, 2, 9, 5, 6]
ディレクション
//[key: value]で入力
let a = ["Taro": 1985, "Hanako": 1990]
let b = a["Taro"] //=>1985
let c = a["Hanako"] //=>1990
//型が明確であれば宣言は省略も出来る
var d: [String: Int] = ["Taro": 1985, "Hanako": 1990]
//存在しないkeyを指定した場合はその値が追加される
d["Jiro"] = 1880
print(d) //=> ["Taro": 1985, "Hanako": 1990, "Jiro": 1880]
//存在するkeyが指定された場合、その値が変更される
d["Taro"] = 2000
print(d) //=> ["Hanako": 1990, "Taro": 2000, "Jiro": 1880]
//removeValueでforkeyで指定したkeyの値を削除出来る
d.removeValue(forKey: "Hanako")
print(d) //=> ["Taro": 2000, "Jiro": 1880]
ループ処理
//定数timesに10を入力
let times: Int = 10
//0〜10未満(9)まで繰り返し処理
for i in 0..<times {
print(i) //=> 0,1,2,3,4,5,6,7,8,9
}
//0〜10まで繰り返し処理
for i in 0...times {
print(i) //=> 0,1,2,3,4,5,6,7,8,9,10
}
//繰り返しで値を追加していく
//変数aで空の配列を指定
var a: [Int] = []
//繰り返し処理でaにiの値と追加
for i in 0..<times {
a.append(i)
}
print(a) //=> [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
//aに入っっている値を順番に出力
for i in a {
print(i) //=> 0,1,2,3,4,5,6,7,8,9
}
条件分岐と組み合わせると以下のような書き方ができる
//空の配列を作成
var a: [Int] = []
for i in 0..<10 {
//もし、iを2で割った余りが0である場合、つまり偶数である場合
if i % 2 == 0 {
a.append(i)
}
}
print(a) //=> [0, 2, 4, 6, 8]
var b: [Int] = []
for i in 0..<10 {
// 3で割り切れる場合
if i % 3 == 0 {
//値を3倍して追加
b.append(i * 3)
}else{
//値をそのまま追加
b.append(i)
}
}
print(b) //=> [0, 1, 2, 9, 4, 5, 18, 7, 8, 27]
関数とスコープについて
funcで関数を作成する事ができる。また、関数の外で宣言した変数、定数は関数内でも使用できる
let b = 123
//関数cの宣言
func c() {
if b == 123 {
print("Hi!")
}
}
c() //=> Hi!
ただし、関数内で宣言した変数、定数は関数の外では呼び出すことができない
func d() {
let e = 456
print(e)
}
d() //=> 456
//定数eは関数の外では呼び出すことができない
print(e) //=> Cannot find 'e' in scope
引数と返り値
引数は関数名の後ろの()内に記述
let a = 4
let b = 6
//add1の()内で値と型を宣言することで、外部から値を受け取ることが出来る
func add1(c: Int, d: Int) {
let e = c + d
print(e)
}
//引数にc = a, d = bを指定
add1(c: a, d: b) //=> 10
返り値は型を指定することで取得できる
//->以降に返り値の型を指定(今回はInt)
func add2(c: Int, d: Int) -> Int {
let e = c + d
return e
}
let f = add2(c: a, d: b)
print(f) //=> 10
クラスとインスタンス
//class = たい焼きの型、インスタンス = たいやき(name = 中身の味)
class Dog {
var name = ""
//クラスの中に書かれた関数をメソッドという
func bark() {
let message = name + ": Bow-wow!"
print(message)
}
}
//定数pochiにclass Dogを代入
let pochi = Dog()
//class Dog内のnameに"Pochi"を代入
pochi.name = "Pochi"
//class内のfunction barkを実行
pochi.bark() //=> Pochi: Bow-wow!
let hachi = Dog()
hachi.name = "HAachi"
hachi.bark() //=> HAachi: Bow-wow!
インスタンスと型
インスタンスプロパティと型プロパティ
インスタンスプロパティの場合はインスタンスを生成してからプロパティにアクセス
一方staticと付けて型プロパティにすることで、クラス名+プロパティの記述が出来る
class Dog {
// インスタンスプロパティ
var name = ""
// 型プロパティ
static var breed = ""
}
//インスタンスプロパティの場合はインスタンスを生成してからプロパティにアクセスする
let pochi = Dog()
pochi.name = "Pochi"
pochi.name //=> Pochi
//型プロパティの場合はインスタンスを生成しなくてもプロパティにアクセスできる
Dog.breed = "Akitaken"
Dog.breed //=> Akitaken
インスタンスメソッドと型メソッド
インスタンスメソッドの場合はインスタンスを生成してからメソッドの実行
一方staticと付けて型メソッドにすることで、クラス名+メソッドの記述が出来る
class Dog {
// インスタンスメソッド
func bark() {
print("Bow-wow!")
}
static func barkStatic() {
print("Bow-wow-wow!")
}
}
インスタンスメソッドの場合はンスタンスを生成してからメソッドの実行
let pochi = Dog()
pochi.bark() //=> Bow-wow!
型メソッドは、インスタンスを作成しなくてもメソッドが実行できる
Dog.barkStatic() //=> Bow-wow-wow!
イニシャライザ
さらにイニシャライザを用いることで短縮してインスタンスを生成し、プロパティを設定することが出来る
class Dog {
var name = ""
var age = 0
// initはfuncがいらない、()内で型の指定が必要
init(name: String, age: Int) {
self.name = name
self.age = age
}
}
let pochi = Dog(name: "Pochi", age: 5)
pochi.name //=> Pochi
pochi.age //=> 5
クラスの継承
class Dog{
var name = ""
func bark() {
let message = name + ": Bow-wow!"
print(message)
}
}
//:の後に他のクラスを書くことでクラスの継承が出来る。この場合はDogを継承
//継承元のメソッドや、プロパティを使用できる
class Shibainu: Dog {
var age = 0
func sayAge() {
let message = name + ": Im \(age) years old"
print(message)
}
}
let taro = Shibainu()
taro.name = "Taro"
taro.bark() //=> Taro: Bow-wow!
taro.sayAge() //=> Taro: Im 0 years old
構造体
スッキリとコンパクトにデータをまとめることが出来る
struct Dog {
var name = ""
var breed = ""
}
let pochi = Dog(name: "Pochi", breed: "Akitaken")
pochi.name //=> Pochi
pochi.breed //=> Akitaken
//pochiはletで定数とされているので下記のように再代入はできない、varに変更すれば実行可能
//pochi.name = "Taro" //=> Cannot assign to property: 'pochi' is a 'let' constant
struct Cat {
var name: String?
var breed: String?
}
let tama = Cat(name: "Tama", breed: nil)
tama.name //=> Tama
tama.breed //=> nil
列挙型
enumで列挙型の作成が出来る
作成した列挙型で、条件分岐などが行える
enum Signal {
//中身をcaseで指定
case Blue
case Red
case Yellow
case Green
}
var sig: Signal
sig = Signal.Blue
//Signalは省略できる
sig = .Blue
//sigの値に応じて条件分岐(switch)
switch sig {
// blueであるなら
case .Blue:
print("Go!")
// redであるなら
case .Red:
print("Stop!")
// yellowであるなら
case .Yellow:
print("Cation!")
// greenであるなら
case .Green:
print("Hi")
}
値渡しと参照渡し
//クラスの場合は参照渡しになる
class Dog {
var age = 0
}
var pochi = Dog()
pochi.age = 5
var hachi = pochi
hachi.age = 7
//hachiの値に値を代入するとpochiの値も変化してしまう
pochi.age //=> 7
hachi.age //=> 7
//構造体の場合には値渡しになる
struct Cat {
var age = 0
}
var tama = Cat()
tama.age = 5
//新しくインスタンスが生成
var mike = tama
mike.age = 7
tama.age //=> 5
mike.age //=> 7
//数値や文字列は値渡しになる
var a = 5
var b = a
b = 7
a //=> 5
b //=> 7
プロトコル
クラスや構造体に一定のルールをもたらすことが出来る
//fish = プロトコル名
protocol fish {
// プロパティが一つ、メソッドがひとつ
var color: String {get set}
func swim()
}
//クラスの作成
//プロトコルはクラスの継承と同じように書く、複数書く場合は,を入れて書く
class Shark: fish {
var color: String = "Blue"
func swim() {
print("Now quickry swiming...")
}
}
//構造体の作成
struct Ray: fish {
var color: String = "Blown"
func swim() {
print("Now slowly swiming...")
}
}
デリゲード
//オブジェクト間の連携をスムーズにする、プロトコルを用いる
protocol SarfinDelegate {
func didEatSardin()
}
class Sardin {
var delegate: SarfinDelegate?
func eaten() {
print("I was eaten")
// ?はnil出ない場合のみメソッドを実行する
delegate?.didEatSardin()
}
}
class Shark: SarfinDelegate {
func eat() {
let sardine = Sardin()
sardine.delegate = self
sardine.eaten()
}
func didEatSardin() {
print("I ate a sardin")
}
}
let shark = Shark()
shark.eat()