6. Swift is “Objective-C without the C”
? Swift言語の開発は2010年7月にAppleエンジニアの
個人プロジェクトから始まった
? 設計するにあたって影響を受けた言語は Objective-C、
Rust、Haskell、Ruby、Python、C#、 CLU等
via: http://jp.techcrunch.com/2014/06/05/20140604apples-new-programming-language-has-been-in-development-for-nearly-four-years/#Swift
24. 特別な評価式
var optional :String? = “foo”
if let notOptional = optional {
println(“(notOptional) is not nil”)
} else {
println(“nil”)
}
optionalのnil判定を行い、代入しつつbool値を返す
ImplicitlyUnwrappedOptional
27. class Users {
class User {
var name: String = "taketin"
}
var user: User? = User()
}
OptionalChaining
28. class Users {
class User {
var name: String = "taketin"
}
var user: User? = User()
}
OptionalChaining
var users: Users? = Users()
if let name = users?.user?.name {
println(name) // “taketin”
} else {
println("error!")
}
29. class Users {
class User {
var name: String = "taketin"
}
var user: User? = nil
}
OptionalChaining
var users: Users? = Users()
if let name = users?.user?.name {
println(name)
} else {
println("error!") // error!
}
56. enum Fukuoka {
case Tenjin
case Daimyo
case Hakata
case Nakasu
}
列挙型 (Enum)
var foo = Fukuoka.Tenjin
switch foo {
case .Tenjin
case .Daimyo
case .Hakata
case .Nakasu
}
57. enum Fukuoka {
case Tenjin
case Daimyo
case Hakata
case Nakasu
}
列挙型 (Enum)
var foo = Fukuoka.Tenjin
switch foo {
case .Tenjin
case .Daimyo
case .Hakata
}
switch must be exhaustive, consider adding a default clause
58. enum Rank: Int {
case One = 1
case Two, Three, Four
}
列挙型 (Enum)
59. enum Rank: Int {
case One = 1
case Two, Three, Four
}
var rank = Rank.Two // (Enum Value)
列挙型 (Enum)
60. enum Rank: Int {
case One = 1
case Two, Three, Four
}
var rank = Rank.Two // (Enum Value)
rank.toRaw() // 2
列挙型 (Enum)
61. enum Rank: Int {
case One = 1
case Two, Three, Four
}
var rank = Rank.Two // (Enum Value)
rank.toRaw() // 2
Rank.fromRaw(3) // (Enum Value)
列挙型 (Enum)
62. enum Fukuoka: String {
case Tenjin = "天神"
case Hakata = "博多"
}
var city = Fukuoka.Hakata
列挙型 (Enum)
63. enum Fukuoka: String {
case Tenjin = "天神"
case Hakata = "博多"
}
var city = Fukuoka.Hakata
city = .Tenjin // 型が分かっているので省略可能
列挙型 (Enum)
64. enum Fukuoka: String {
case Tenjin = "天神"
case Hakata = "博多"
func toKana() -> String {
switch self {
case .Tenjin: return "てんじん"
case .Hakata: return "はかた"
}
}
}
列挙型 (Enum)
65. enum Fukuoka: String {
case Tenjin = "天神"
case Hakata = "博多"
func toKana() -> String {
switch self {
case .Tenjin: return "てんじん"
case .Hakata: return "はかた"
}
}
}
列挙型 (Enum)
var city = Fukuoka.Tenjin // 天神
66. enum Fukuoka: String {
case Tenjin = "天神"
case Hakata = "博多"
func toKana() -> String {
switch self {
case .Tenjin: return "てんじん"
case .Hakata: return "はかた"
}
}
}
列挙型 (Enum)
var city = Fukuoka.Tenjin // 天神
city.toKana() // てんじん
68. Associated Values
enum APIResponse {
case Success(Int, String)
case Error(Int, String, NSError)
}
// if success
var res = APIResponse.Success(200, “OK”)
列挙型 (Enum)
69. Associated Values
enum APIResponse {
case Success(Int, String)
case Error(Int, String, NSError)
}
// if success
var res = APIResponse.Success(200, “OK”)
// if error
var res = APIResponse.Error(403, “Access denied”, error)
列挙型 (Enum)
70. Associated Values
switch res {
case let .Success(httpStatus, message):
… // 成功時処理
case let .Error(httpStatus, message, error):
… // エラー処理
}
列挙型 (Enum)
71. Associated Values
switch res {
case let .Success(httpStatus, message):
… // 成功時処理
case let .Error(httpStatus, message, error):
… // エラー処理
}
a.k.a
discriminated unions, tagged unions, or variants.
列挙型 (Enum)
105. 比較 (===)
var foo1 = FooClass()
var foo2 = FooClass()
foo1 === foo2 // false
クラス
106. 比較 (===)
var foo1 = FooClass()
var foo2 = FooClass()
foo1 === foo2 // false
var foo3 = foo1
foo3 === foo1 // true
クラス
107. 比較 (===)
var foo1 = FooClass()
var foo2 = FooClass()
foo1 === foo2 // false
var foo3 = foo1
foo3 === foo1 // true
インスタンスのアドレス比較を行う
クラス
108. Getter, Setter
class Foo {
var bar: Int {
get { return 10 }
set { self.baz = newValue }
}
var baz: Int = 0
}
クラス - プロパティ
109. Getter, Setter
class Foo {
var bar: Int {
get { return 10 }
set { self.baz = newValue }
}
var baz: Int = 0
}
setter は “newValue” で新しい値を参照できる
クラス - プロパティ
110. Getter, Setter
class Foo {
var bar: Int {
get { return 10 }
}
var baz: Int = 0
}
get のみ書く事で ReadOnly として定義できる
クラス - プロパティ
125. protocol FooProtocol {
var bar: String { get }
func baz() -> String
}
class FooClass : FooProtocol {
var bar: String = “hoge”
func baz() -> String { /* Snip */ }
}
Protocol
126. protocol FooProtocol {
var bar: String { get set } // getter, setter 必須
func baz() -> String
}
class FooClass : FooProtocol {
var bar: String {
get { /* Snip */ } // set が無いのでコンパイルエラー
}
Protocol
127. protocol FooProtocol {
var bar: String
mutating func baz() -> String
}
struct FooStruct : FooProtocol {
var bar: String = “hoge”
mutating func baz() -> String { /* Snip */ }
}
Protocol
133. 型制約無し
func repeat<T>(item: T, times: Int) -> T[] {
var result = T[]()
for i in 0..times {
result += item
}
return result
}
Generics
134. 型制約無し
func repeat<T>(item: T, times: Int) -> T[] {
var result = T[]()
for i in 0..times {
result += item
}
return result
}
repeat(“knock”, 4) // [“knock”, “knock”, “knock”, “knock”]
Generics
135. 型制約無し
func repeat<T>(item: T, times: Int) -> T[] {
var result = T[]()
for i in 0..times {
result += item
}
return result
}
repeat(“knock”, 4) // [“knock”, “knock”, “knock”, “knock”]
repeat(10, 4) // [10, 10, 10, 10]
Generics
136. 型制約有り
func findIndex<T: Equatable>(array: T[], valueToFind: T) -> Int? {
for (index, value) in enumerate(array) {
if value == valueToFind {
return index
}
}
return nil
}
Generics
137. 型制約有り
func findIndex<T: Equatable>(array: T[], valueToFind: T) -> Int? {
for (index, value) in enumerate(array) {
if value == valueToFind {
return index
}
}
return nil
}
プロトコル継承の制約を定義できる
Generics
139. Any & AnyObject
// 関数型以外なんでも入れる事ができる
var array : Any[] = ["1", 2, Foo()]
TypeCasting
140. Any & AnyObject
// 関数型以外なんでも入れる事ができる
var array : Any[] = ["1", 2, Foo()]
var array2 : AnyObject[] = [Foo(), Bar(), Baz()]
TypeCasting
141. Any & AnyObject
// 関数型以外なんでも入れる事ができる
var array : Any[] = ["1", 2, Foo()]
// クラスのインスタンスのみ入れる事ができる
var array2 : AnyObject[] = [Foo(), Bar(), Baz()]
TypeCasting
142. 型チェック
var array : Any[] = ["1", 2, 3]
for obj in array {
if obj is Int {
println("(obj) is Int") // 2 is Int & 3 is Int
}
}
TypeCasting
143. ダウンキャスト
// obj には Base クラスのインスタンスが入っている
// Base を継承した Bar クラスが定義されている
let bar = obj as Bar // Bar クラス
TypeCasting
144. ダウンキャスト
// obj には Base クラスのインスタンスが入っている
// Base を継承した Bar クラスが定義されている
let bar = obj as Bar
もし obj に Bar へダウンキャストできないオブジェクトが入って
いたらランタイムエラー
TypeCasting
145. ダウンキャスト
// obj には Base クラスのインスタンスが入っている
// Base を継承した Bar クラスが定義されている
let bar = obj as? Bar
オプショナルで安全
TypeCasting
146. ダウンキャスト
for obj in array {
if obj is Bar {
let bar = obj as Bar
/* Snip */
}
}
TypeCasting
for obj in array {
if let bar = obj as? Bar {
/* Snip */
}
}
147. ダウンキャスト
for obj in array {
if obj is Bar {
let bar = obj as Bar
/* Snip */
}
}
TypeCasting
for obj in array {
if let bar = obj as? Bar {
/* Snip */
}
}
OptionalValue の評価式を使って、評価 > 代入が簡単に書ける
157. “Namespacing is implicit in swift, all classes (etc) are implicitly
scoped by the module (Xcode target) they are in. no class
prefixes needed”
「Swiftにおいて名前空間は暗黙のうちに提供される。すべてのクラ
スはそのモジュール (Xcode上のターゲット)によって暗黙のうちに
スコープが制限される。クラスプレフィックスはもはや不要」
via: https://twitter.com/clattner_llvm/status/474730716941385729
おまけ:名前空間
159. アクセス修飾子 (private, public)
"We don't usually promise anything for the future, but in this
case we are making an exception. Swift will have access
control mechanisms."
「将来の約束は一般的にしてないんだけど、今回は例外。Swift
にはアクセス制限のための仕組みを追加予定です」
via: http://stackoverflow.com/questions/24003918/does-swift-have-access-modifiers
おまけ:今後の展望