原文: Apple Inc. “The Swift Programming Language”。 iBooks. https://itun.es/jp/jEUH0.l
#Swiftツアー
その2からの続きです
プロトコル・拡張
プロトコル(インターフェース)
- プロトコルの宣言にはprotocolを使用します
protocol ExampleProtocol {
var simpleDescription: String { get }
mutating func adjust()
}
- クラス、列挙体、構造体はプロトコルを継承することができます
class SimpleClass: ExampleProtocol {
var simpleDescription: String = "A very simple class."
var anotherProperty: Int = 69105
func adjust() {
simpleDescription += " Now 100% adjusted."
}
}
var a = SimpleClass()
a.adjust()
let aDescription = a.simpleDescription
struct SimpleStructure: ExampleProtocol {
var simpleDescription: String = "A simple structure"
mutating func adjust() {
simpleDescription += " (adjusted)"
}
}
var b = SimpleStructure()
b.adjust()
let bDescription = b.simpleDescription
- SimpleStructureにあるmutatingは、メンバの値を変更するメソッドであることを意味しています
- ただし、クラスのメソッドはプロパティを変更することは一般的なことなので、mutatingをつける必要はありません
###拡張
- extensionを使い、既にある型に新しいメソッドやプロパティを追加することができます
- 既に定義されている型に対してプロトコルを付与することができ、インポートしたライブラリやフレームワークで宣言されている型に対しても使用できます
extension Int: ExampleProtocol {
var simpleDescription: String {
return "The number \(self)"
}
mutating func adjust() {
self += 42
}
}
7.simpleDescription
- プロトコル名は他の型名と同じ様に使うことができます。例えば、一つの同じプロトコルを継承しているそれぞれ違う型のオブジェクトの配列を作りたいときは、プロトコル名で配列をつくります
- プロトコル型の値は、プロトコル定義外で実装されているメソッドにはアクセスできません
let protocolValue: ExampleProtocol = a
protocolValue.simpleDescription
// protocolValue.anotherProperty // Uncomment to see the error
- 上記の定数protocolValueにはSimpleClass型の値が代入されていますが、ExampleProtocol型で定義しているので、ExampleProtocol型として扱われます。プロトコルに後で追加された変数に誤ってアクセスしようとしてもエラーを返します。
ジェネリック
- 名前を<>の中に書くことでジェネリックの型や関数をつくることができます
func repeat<ItemType>(item: ItemType, times: Int) -> ItemType[] {
var result = ItemType[]()
for i in 0..times {
result += item
}
return result
}
repeat("knock", 4)
- ジェネリックのクラス、列挙体や構造体、関数やメソッドもつくることができます
// Reimplement the Swift standard library's optional type
enum OptionalValue<T> {
case None
case Some(T)
}
var possibleInteger: OptionalValue<Int> = .None
possibleInteger = .Some(100)
- whereを型の後ろに使うことで、必要な条件を指定することができます。例えば、プロトロルを継承していること、2つの型は同じであること、特定のスーパークラスをもったクラスであること等です。
func anyCommonElements <T, U where T: Sequence, U: Sequence, T.GeneratorType.Element: Equatable, T.GeneratorType.Element == U.GeneratorType.Element> (lhs: T, rhs: U) -> Bool {
for lhsItem in lhs {
for rhsItem in rhs {
if lhsItem == rhsItem {
return true
}
}
}
return false
}
anyCommonElements([1, 2, 3], [3])
- whereを省略して、プロトコルやクラス名をコロンの後に書くことも出来ます。<T: Equatable>は<T where T: Equatable>と同じ意味です