Created
February 17, 2016 15:21
-
-
Save SatoTakeshiX/a6aa752a83f542e8df3d to your computer and use it in GitHub Desktop.
【朝活】iOS開発会議 in beez渋谷50回目 サンプルコード
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
//: Playground - noun: a place where people can play | |
import UIKit | |
/* | |
プロトコル:実装を伴わない宣言の集合。インターフェース。クラス、構造体、列挙型を定義するとき、プロトコルを指定して、そのプロトコルが宣言しているメソッドなどを宣言。継承できない構造体でも、プロトコルに定義されているインターフェースの実装が保証される。 | |
「用語」 | |
プロトコルを採用する->プロトコルを使ってクラス、構造体、列挙型を定義する | |
プロトコルに適合する。プロトコルに準拠する->プロコトルを採用したクラス、構造体、列挙型 | |
Swiftでプロトコルで宣言できるもの | |
・インスタンスメソッド、タイプメソッド | |
・関数宣言 | |
・インスタンスプロパティ、タイププロパティ | |
・イニシャライザ | |
・添字付け | |
・typealias宣言 | |
*/ | |
/* | |
プロトコルの文法 | |
*/ | |
//ネズミっぽい食べ方ができるプロトコル | |
protocol MouseEatable{ | |
//インスタンスプロパティは var <プロパティ名> : 型 { get set } | |
//setterを強制させるプロパティ | |
var cheekpouch : Int { get set }//ほおぶくろ | |
//{get}のみは実装時にsetterをつけてもよい。つけなくてもよい | |
var tooth : Int { get } //歯の数 | |
//メソッドは func <メソッド名> (引数 : 引数の型 ) -> 返り値の型 | |
//自分のプロパティを操作するならmutatingをつける | |
mutating func storeFood (number : Int) ->Int//ほおぶくろに食べ物をいれる | |
} | |
//動物の生活形式 | |
protocol FormOfLife{ | |
//タイププロパティは staticをつける | |
//staticなら構造体、列挙型、クラスどれでもタイプメソッドがつくれる | |
static var isNocturnality : Bool { get } //夜行性かどうか | |
var myName : String { get }//自分の名前 | |
//初期化も宣言できる | |
init(name : String) | |
} | |
//クラスのみのプロトコルは classをつける | |
protocol OnlyClassProtocol : class { | |
//クラスのタイププロパティもstatic | |
static func typeClassMethod() | |
} | |
//プロトコルを採用。複数採用するときはカンマ(,)で指定する | |
struct Hamster : MouseEatable, FormOfLife { | |
let myName : String | |
//プロトコル宣言ではget setなのでletではなくvarで実装しなければいけない | |
var cheekpouch = 10 //どんぐりを10個入れれるほうぶくろ | |
//get なので letでも実装できる。varでも実装できる。プロトコルでgetで宣言されたものは実装するときはgetter,setterどちらも実装できるようにしてもよい。 | |
let tooth = 16 //歯は16本。 | |
//夜行性 | |
static let isNocturnality : Bool = true | |
//ほおぶろくに入れるメソッド | |
mutating func storeFood(number : Int) -> Int { | |
self.cheekpouch = self.cheekpouch + number | |
return self.cheekpouch | |
} | |
//初期化メソッド | |
init(name: String) { | |
myName = name | |
} | |
} | |
//クラスでもプロトコルを採用する | |
// class <クラス名> : superClass , Protocol1, Protocol2{} | |
class Cat : FormOfLife { | |
static let isNocturnality = false//夜行性ではない | |
let myName : String//自分の名前 | |
//プロトコルの初期化メソッドはクラスの時はrequiredをつける | |
required init(name: String) { | |
myName = name | |
} | |
} | |
/* | |
プロトコルを型として使う | |
*/ | |
var hamham = Hamster(name: "ハムハム")//構造体 | |
var mike = Cat(name: "ミケ")//クラス | |
//プロトコルが同じなら型指定して配列に入れられる | |
let petList : [FormOfLife] = [hamham, mike] | |
//同じプロトコルが指定されているので、プロパティを同じように利用できる | |
for pet in petList{ | |
//ペットの名前を確認 | |
print(pet.myName) | |
} | |
/* | |
プロトコルの継承 | |
プロトコルを宣言するときに、別のプロトコルを継承することができる。新しく宣言したプロトコルは継承先のプロトコルの内容を引き継ぐ | |
*/ | |
//ハムスターの食べ方ができるプロトコルHamsterEatableをMouseEatableを継承して作成する | |
protocol HamsterEatable : MouseEatable{ | |
//ひまわりのタネ | |
var sunflowerSeed : Int { get set} | |
} | |
//継承したプロトコルを採用する | |
class Djungarian : HamsterEatable { | |
//継承先(HamsterEatable)のプロパティ | |
var sunflowerSeed = 10 | |
//継承元(MouseEatable)のプロトコル | |
var cheekpouch = 0 | |
var tooth = 0 | |
func storeFood (number : Int) ->Int{ | |
return number | |
} | |
} | |
//インスタンスを作る | |
let djungarian = Djungarian() | |
/* | |
プロトコルが適合するかをチェックする | |
is | |
式 is someprotocol | |
式がプロトコルに適合したらtrue、そうでないならfalse | |
as? | |
式 as? someprotocol | |
式が型としてのプロトコルのオプショナルにダウンキャストされる。式がプロコトルに適合していなかったらnilを返す | |
as! | |
式 as! someprotocol | |
式が型としてのプロトコルにダウンキャストされる。式がプロトコルに適合していなかったら実行時エラー | |
*/ | |
//プロトコルを採用していないクラスを作る | |
class Rock { | |
let width : Int = 0 | |
let height : Int = 0 | |
let length : Int = 0 | |
} | |
//インスタンスを作る | |
let rock = Rock() | |
//AnyObjectで配列を作る | |
let list : [AnyObject] = [djungarian, rock] | |
//プロコトルを採用しているかをループで回して確認する | |
for object in list{ | |
//as?でプロトコルを採用しているかどうかをみる | |
if let object = object as? HamsterEatable { | |
print("\(object)はひまわりの種は \(object.sunflowerSeed)個ある") | |
} else { | |
print("\(object)はひまわりの種はもってない") | |
} | |
// isはプロトコルを採用していればtrueを返す。していなければfalseを返す | |
if object is HamsterEatable{ | |
print("\(object)はひまわりの種を持っている") | |
} | |
} | |
//プロコトルの合成 | |
//複数のプロコトルの型指定をする事ができる | |
//変数: protocol<protocol1, protocol2> | |
//職業プロトコル | |
protocol Job { | |
var jobName : String { get set } | |
} | |
//住所プロコトル | |
protocol Adress { | |
var adressName : String { get set } | |
} | |
struct Person :Job, Adress { | |
var jobName = "エンジニア" | |
var adressName = "東京" | |
} | |
//プロコトルJobとAdressをどちらも採用している変数を引数にする関数を作る | |
func Identification (person : protocol<Job, Adress>) -> String{ | |
return "あなたの職業は\(person.jobName)で、お住いは\(person.adressName)です" | |
} | |
let sato = Person() | |
print(Identification(sato)) | |
//デリゲートパターン | |
//->プロジェクトでつくる | |
//プロトコルの拡張でデフォルトの実装を作る! | |
//Swift2からの追加機能 | |
//鳴き声のプロトコル | |
protocol Criable { | |
//どんな鳴き声で泣くのか | |
var cryString : String { get } | |
//叫び声 | |
var roarString : String { get } | |
//実際に泣くメソッド | |
func cry() -> String | |
} | |
//extensionでプロパティ、メソッドのデフォルト実装を作ることができる | |
extension Criable { | |
//鳴き声メソッド | |
//鳴き声を2回繰り返す | |
func cry() -> String { | |
return cryString + cryString | |
} | |
//叫び声はデフォルトを作る | |
//ストアドプロパティは作れない。 | |
var roarString : String { | |
return "ガオー" | |
} | |
} | |
//猿の構造体 | |
struct Monkey : Criable { | |
let cryString : String | |
//プロトコル拡張で実装したものは構造体宣言時に改めて実装してもよいみたい | |
//let roarString : String = "うが~" | |
//func cry() -> String { | |
// return cryString + cryString + cryString | |
//} | |
} | |
//ゴリラを作る | |
let gorilla = Monkey(cryString: "ウホ") | |
print(gorilla.cry()) | |
print(gorilla.roarString) | |
//チンパンジーを作る | |
let chimpanzee = Monkey(cryString: "ウッキー") | |
print(chimpanzee.cry()) | |
//既存のプロトコルを拡張する。 | |
//Array型に採用されているCollectionTypeというプロトコルを拡張する。 | |
extension CollectionType where Generator.Element :Criable{ | |
var cryString : String{ | |
//各要素の鳴き声 | |
let crysAsText = self.map{ $0.cry()} | |
return "[" + crysAsText.joinWithSeparator(", ") + "]" | |
} | |
} | |
let monkeys = [gorilla, chimpanzee] | |
//Array型の変数にcryStringを追加できた!! | |
print(monkeys.cryString) | |
/* | |
参考資料 | |
http://tea-leaves.jp/swift/content/%E3%83%97%E3%83%AD%E3%83%88%E3%82%B3%E3%83%AB | |
Swift : クラス継承とプロトコル拡張を比べてみる #yidev | |
http://www.slideshare.net/tomohirokumagai54/swift-yidev | |
http://tea-leaves.jp/swift/content/%E3%83%97%E3%83%AD%E3%83%88%E3%82%B3%E3%83%AB | |
->ちょっと古い?? | |
WWDC | |
https://developer.apple.com/videos/play/wwdc2015-408/ | |
*/ | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment