Swift/extension
をテンプレートにして作成
[
トップ
] [
新規
|
一覧
|
単語検索
|
最終更新
|
ヘルプ
|
ログイン
]
開始行:
[[Swift]]
*Swift/拡張 [#v41b7c0c]
ソースコードを書き換えたり継承を使ったりすることなく、
既に存在する肩に新しいメソッドやプロパティを付け加える機...
Swiftの「拡張 (extension)」である。
extension 型名 : [ プロトコル列 ] {
[ イニシャライザ定義 ]
[ 計算型プロパティ定義 ]
[ メソッド定義 ]
[ その他(型定義、添字付け定義、など)の定義 ]
}
拡張に記述できる定義は以下の通り。
-計算型のインスタンスプロパティ、計算型のタイププロパティ
-インスタンスメソッド、タイプメソッド
-イニシャライザ
-添字付け
-(拡張の内部で使用する)ネスト型定義
拡張機能を使って、クラスや構造体をそれまで適合していなか...
拡張に記述できないのは次の通り。
-格納型のインスタンスプロパティ、格納型のタイププロパティ
-プロパティオブザーバ
-すでに定義されている内容の上書き
**システムの既存の型に対する拡張定義の例 [#p61b2487]
extension String {
var length: Int {
return self.characters.count // インスタンス自体...
}
}
let s = "オーハ\u{3099}ーロート\u{3099}"
print(s, s.length) // オーバーロード 7 と表示される
CGRectに対する拡張定義の例
import Cocoa
extensions CGRect {
init(points p1:CGPoint, _ p2:CGPoint) {
var ox,oy, w, h: CGfloat
(ox, w) = p1.x < p2.x ? (p1.x, p2.x-p1.x) : (p2.x, p...
(oy, h) = p1.y < p2.y ? (p1.y, p2.y-p1.y) : (p2.y, p...
self.origin = CGPoint(x:ox, y:oy)
self.size = CGSize(width:w, height: h)
}
subscript (i:Int) -> CGPoint {
var p = self.origin
if i == 1 || i == 2 {
p.x += self.width
}
if i == 2 || i == 3 {
p.y += self.height
}
return p
}
}
let p1 = CGPoint(x:10.0, y:105.0)
let p2 = CGPoint(x:130.0, y:15.0)
let rect = CGRect(points: p1, p2)
print(rect) // (10.0, 15.0, 120.0, 90.0) と表示される
for i in 0...2 {
print(rect[i], terminator:", ")
}
print(rect[3]) // (10.0, 15.0), (130.0, 15.0), (130.0, ...
***拡張定義とイニシャライザ [#veeda3e5]
- 値型の定義の場合。~
イニシャライザの定義がなく、default initializer または me...
拡張定義でイニシャライザを追加した後も、既存の default in...
memberwise initializer を利用し続けることができる。
-クラスの場合~
拡張定義にdesignated initializer を記述することはできない...
convenience initializerの記述はできる。
デイニシャライザを拡張定義に含めることはできない。
***拡張定義と継承 [#h2be77d6]
あるクラスに対して拡張定義を追加した場合、その定義はサブ...
ただし、拡張定義中の記述は final がついているものとして扱...
サブクラスで上書きすることはできない。
*拡張定義とプロトコルへの適合 [#e38b4910]
クラス、構造体、列挙型に対する拡張定義にはプロトコルを指...
そのプロトコルに適合するように拡張機能で実装しなくてはな...
プロトコル FloatLiteralConvertible の宣言
protocol FloatLiteralConvertible {
typealias FloatLiteralType
init(floatLiteral value: Self.FloatLiteralType)
}
Ounce+Ext.swift というファイルの内容
extension Ounce : FloatLiteralConvertible {
init(floatLiteral value: Double) { self.init(ounce: va...
}
次のmain.swift を Ounce+Ext.swift と一緒にコンパイルして...
var a: Ounce
a = 10.0
print("\(a.mL)mL") // 295.735mL と表示される
ただし、代入できるようになったのは実数のリテラルだけなの...
var a: Ounce
let v = 10.0
a = v // エラー
** プロトコルに適合するための定義がすでに存在する場合 [#z...
enum Grade {
case 秀, 優, 良, 可, 不可, 放棄
var boolValue: Bool {
switch self {
case 秀, 優, 良, 可: return true
default: return false
}
}
public protocol BooleanType {
public var boolValue: Bool { get }
}
列挙型 Grade は既に BooleanType プロトコルに適合している...
Gradeのソースプログラムを変更できない場合には拡張定義の記...
適合を宣言できる。
extension Grade : BooleanType { } // プロトコルに適合...
**プロトコルが演算子の定義を含む場合 [#l4122edd]
前章で扱ったプロトコル Equatable は演算子 == の定義だけを...
拡張定義でプロトコル Equatable に適合させるには、トップレ...
さらに空の拡張定義が必要となる。
extension DayOfMonth : Equatable {}
func ==(lhs: DayOfMonth, rhs: DayOfMonth) -> Bool {
return lhs.month == rhs.month && lhs.day == rhs.day
}
*プロトコル拡張 [#eb4655dd]
protocol Datable {
var year: Int { get }
var month: Int { get }
var day: Int { get }
}
プロトコル Datable に対する拡張定義
func Zeller(var m:Int, _ d:Int, var _ y:Int) -> Int { /*...
extension Datable {
var dayOfWeek: Int {
return Zeller(month, day, year)
}
}
struct Date : Daytable {
var year, month, day: Int
}
let d1 = Date(year: 2016, month: 6, day: 8)
print(d1) // Date(year: 2016, month: 6, day: 8)
print(d1.dayOfWeek) // 3 と表示される(水曜日を表す数字)
データ型が採用したプロトコルにプロトコル拡張( protocol ex...
そのデータ型ではプロトコル拡張の定義を利用できるし、必要...
つまり、プロトコル拡張では、
メソッドやプロパティのデフォルトの実装 (default implement...
を記述できるといえる。
protocol Datable {
var year: Int { get }
var month: Int { get }
var day: Int { get }
var isLeap: Bool { get }
}
extension Datable {
var isLeap: Bool {
return (year % 4 == 0) && (year % 100 != 0 || year %...
}
private static func Zeller(var m:Int, _ d:Int, var _ y...
var dayOfweek: Int {
return Self.Zeller(month, day, year)
}
}
default implementation は、それを継承したプロトコルやデー...
その場合、構造体、列挙型、クラス定義でも override を記述...
**プロトコル拡張による多重継承 [#t8d2760c]
protocol DateType {
var year: Int { get }
var month: Int { get }
var day: Int { get }
var area: String? { get } // Timezone
}
extension DateType {
func toString() -> String {
return "\(year). \(month). \(day)"
}
}
protocol TimeType {
var hour: Int { get }
var minute: Int { get }
var area: String? { get } // Timezone
}
extension TypeType {
func toString() -> String {
var s = (hour < 10 ? " " : "") + "\(hour)"
s += ":" + (minute < 10 ? "0" : "") + "\(minute)"
if let a = area { s += " (\(a))" }
return s
}
}
struct Date : DateType, TimeType { // 2つのプロトコル拡...
let year, month, day, hour, minute: Int
let area: String?
init(_ y:Int, _ m:Int, _ d:Int, _ t:(Int, Int), area: ...
year = y; month = m; day = d;
(hour, minute) = t; self.area = area
}
}
次のようなプログラムは、どちらの toString()関数を使ってよ...
let d = Date(2010, 7, 23, (12, 56), area: "JS")
print(d.toString()) // エラーとなる
次の例ではダウンキャストしているので、どちらの toString()...
let dd: DateType = Date(2010, 7, 23, (12, 56), area: "JS")
let dt: TimeType = Date(2010, 7, 23, (12, 56), area: "JS")
print(dd.toString()) // 2010. 7. 28 と表示される
print(dt.toString()) // 12:56 (JST) と表示される
プロトコル拡張のどちらの関数を使用するか指定すればエラー...
extension Date: CustomStringConvertible {
var description: String {
return (self as DateType).toString() + ", " + (self ...
}
}
let d: DateType = Date(2010, 7, 23, (12, 56), area: "JS")
print(d)) // 2010. 7. 28, 12:56 (JST) と表示される
default implementation の利用には注意が必要である。
もしも次のような定義をした場合は、両方のプロトコル拡張に...
extension Date {
func toString() -> String {
return (self as DateType).toString() + ", " + (self ...
}
}
終了行:
[[Swift]]
*Swift/拡張 [#v41b7c0c]
ソースコードを書き換えたり継承を使ったりすることなく、
既に存在する肩に新しいメソッドやプロパティを付け加える機...
Swiftの「拡張 (extension)」である。
extension 型名 : [ プロトコル列 ] {
[ イニシャライザ定義 ]
[ 計算型プロパティ定義 ]
[ メソッド定義 ]
[ その他(型定義、添字付け定義、など)の定義 ]
}
拡張に記述できる定義は以下の通り。
-計算型のインスタンスプロパティ、計算型のタイププロパティ
-インスタンスメソッド、タイプメソッド
-イニシャライザ
-添字付け
-(拡張の内部で使用する)ネスト型定義
拡張機能を使って、クラスや構造体をそれまで適合していなか...
拡張に記述できないのは次の通り。
-格納型のインスタンスプロパティ、格納型のタイププロパティ
-プロパティオブザーバ
-すでに定義されている内容の上書き
**システムの既存の型に対する拡張定義の例 [#p61b2487]
extension String {
var length: Int {
return self.characters.count // インスタンス自体...
}
}
let s = "オーハ\u{3099}ーロート\u{3099}"
print(s, s.length) // オーバーロード 7 と表示される
CGRectに対する拡張定義の例
import Cocoa
extensions CGRect {
init(points p1:CGPoint, _ p2:CGPoint) {
var ox,oy, w, h: CGfloat
(ox, w) = p1.x < p2.x ? (p1.x, p2.x-p1.x) : (p2.x, p...
(oy, h) = p1.y < p2.y ? (p1.y, p2.y-p1.y) : (p2.y, p...
self.origin = CGPoint(x:ox, y:oy)
self.size = CGSize(width:w, height: h)
}
subscript (i:Int) -> CGPoint {
var p = self.origin
if i == 1 || i == 2 {
p.x += self.width
}
if i == 2 || i == 3 {
p.y += self.height
}
return p
}
}
let p1 = CGPoint(x:10.0, y:105.0)
let p2 = CGPoint(x:130.0, y:15.0)
let rect = CGRect(points: p1, p2)
print(rect) // (10.0, 15.0, 120.0, 90.0) と表示される
for i in 0...2 {
print(rect[i], terminator:", ")
}
print(rect[3]) // (10.0, 15.0), (130.0, 15.0), (130.0, ...
***拡張定義とイニシャライザ [#veeda3e5]
- 値型の定義の場合。~
イニシャライザの定義がなく、default initializer または me...
拡張定義でイニシャライザを追加した後も、既存の default in...
memberwise initializer を利用し続けることができる。
-クラスの場合~
拡張定義にdesignated initializer を記述することはできない...
convenience initializerの記述はできる。
デイニシャライザを拡張定義に含めることはできない。
***拡張定義と継承 [#h2be77d6]
あるクラスに対して拡張定義を追加した場合、その定義はサブ...
ただし、拡張定義中の記述は final がついているものとして扱...
サブクラスで上書きすることはできない。
*拡張定義とプロトコルへの適合 [#e38b4910]
クラス、構造体、列挙型に対する拡張定義にはプロトコルを指...
そのプロトコルに適合するように拡張機能で実装しなくてはな...
プロトコル FloatLiteralConvertible の宣言
protocol FloatLiteralConvertible {
typealias FloatLiteralType
init(floatLiteral value: Self.FloatLiteralType)
}
Ounce+Ext.swift というファイルの内容
extension Ounce : FloatLiteralConvertible {
init(floatLiteral value: Double) { self.init(ounce: va...
}
次のmain.swift を Ounce+Ext.swift と一緒にコンパイルして...
var a: Ounce
a = 10.0
print("\(a.mL)mL") // 295.735mL と表示される
ただし、代入できるようになったのは実数のリテラルだけなの...
var a: Ounce
let v = 10.0
a = v // エラー
** プロトコルに適合するための定義がすでに存在する場合 [#z...
enum Grade {
case 秀, 優, 良, 可, 不可, 放棄
var boolValue: Bool {
switch self {
case 秀, 優, 良, 可: return true
default: return false
}
}
public protocol BooleanType {
public var boolValue: Bool { get }
}
列挙型 Grade は既に BooleanType プロトコルに適合している...
Gradeのソースプログラムを変更できない場合には拡張定義の記...
適合を宣言できる。
extension Grade : BooleanType { } // プロトコルに適合...
**プロトコルが演算子の定義を含む場合 [#l4122edd]
前章で扱ったプロトコル Equatable は演算子 == の定義だけを...
拡張定義でプロトコル Equatable に適合させるには、トップレ...
さらに空の拡張定義が必要となる。
extension DayOfMonth : Equatable {}
func ==(lhs: DayOfMonth, rhs: DayOfMonth) -> Bool {
return lhs.month == rhs.month && lhs.day == rhs.day
}
*プロトコル拡張 [#eb4655dd]
protocol Datable {
var year: Int { get }
var month: Int { get }
var day: Int { get }
}
プロトコル Datable に対する拡張定義
func Zeller(var m:Int, _ d:Int, var _ y:Int) -> Int { /*...
extension Datable {
var dayOfWeek: Int {
return Zeller(month, day, year)
}
}
struct Date : Daytable {
var year, month, day: Int
}
let d1 = Date(year: 2016, month: 6, day: 8)
print(d1) // Date(year: 2016, month: 6, day: 8)
print(d1.dayOfWeek) // 3 と表示される(水曜日を表す数字)
データ型が採用したプロトコルにプロトコル拡張( protocol ex...
そのデータ型ではプロトコル拡張の定義を利用できるし、必要...
つまり、プロトコル拡張では、
メソッドやプロパティのデフォルトの実装 (default implement...
を記述できるといえる。
protocol Datable {
var year: Int { get }
var month: Int { get }
var day: Int { get }
var isLeap: Bool { get }
}
extension Datable {
var isLeap: Bool {
return (year % 4 == 0) && (year % 100 != 0 || year %...
}
private static func Zeller(var m:Int, _ d:Int, var _ y...
var dayOfweek: Int {
return Self.Zeller(month, day, year)
}
}
default implementation は、それを継承したプロトコルやデー...
その場合、構造体、列挙型、クラス定義でも override を記述...
**プロトコル拡張による多重継承 [#t8d2760c]
protocol DateType {
var year: Int { get }
var month: Int { get }
var day: Int { get }
var area: String? { get } // Timezone
}
extension DateType {
func toString() -> String {
return "\(year). \(month). \(day)"
}
}
protocol TimeType {
var hour: Int { get }
var minute: Int { get }
var area: String? { get } // Timezone
}
extension TypeType {
func toString() -> String {
var s = (hour < 10 ? " " : "") + "\(hour)"
s += ":" + (minute < 10 ? "0" : "") + "\(minute)"
if let a = area { s += " (\(a))" }
return s
}
}
struct Date : DateType, TimeType { // 2つのプロトコル拡...
let year, month, day, hour, minute: Int
let area: String?
init(_ y:Int, _ m:Int, _ d:Int, _ t:(Int, Int), area: ...
year = y; month = m; day = d;
(hour, minute) = t; self.area = area
}
}
次のようなプログラムは、どちらの toString()関数を使ってよ...
let d = Date(2010, 7, 23, (12, 56), area: "JS")
print(d.toString()) // エラーとなる
次の例ではダウンキャストしているので、どちらの toString()...
let dd: DateType = Date(2010, 7, 23, (12, 56), area: "JS")
let dt: TimeType = Date(2010, 7, 23, (12, 56), area: "JS")
print(dd.toString()) // 2010. 7. 28 と表示される
print(dt.toString()) // 12:56 (JST) と表示される
プロトコル拡張のどちらの関数を使用するか指定すればエラー...
extension Date: CustomStringConvertible {
var description: String {
return (self as DateType).toString() + ", " + (self ...
}
}
let d: DateType = Date(2010, 7, 23, (12, 56), area: "JS")
print(d)) // 2010. 7. 28, 12:56 (JST) と表示される
default implementation の利用には注意が必要である。
もしも次のような定義をした場合は、両方のプロトコル拡張に...
extension Date {
func toString() -> String {
return (self as DateType).toString() + ", " + (self ...
}
}
ページ名: