プロトタイプメソッド
- protocolでcloneメソッドを実装する
- サブクラスでprotocolを継承し、cloneメソッド内で新しくインスタンスを作成し、returnする
- 端的にいえば、クラスに自分のコピーを返却するメソッドを実装すること
- このコピーは別のインスタンスというのが重要(値渡しになる)
メリット
- クラスは参照渡しになるが、cloneを使えば、値渡しになる
- クラスからインスタンスを1から作るのが大変な場合、時間などのコストがかかりすぎる場合
- クラスは通常参照渡しになるが、cloneを使えば、値渡しすることができる
- 複雑な生成処理を気にしないで良い(例: initに値を渡さなければいけない or 生成の手順などを全く気にしなくて良いので使いやすい
protocol Comment {
func clone() -> Comment
func fetchCommentContent() -> [String]
func pushCommentContent(txt: String)
}
class ArticleComment {
private var contents = [String]()
init(contents: [String]) {
self.contents = contents
}
}
extension ArticleComment: Comment {
func clone() -> Comment {
let vc = ArticleComment(contents: self.contents)
return vc
}
func fetchCommentContent() -> [String] {
return self.contents
}
func pushCommentContent(txt: String) {
self.contents.append(txt)
}
}
let comments = ["Amazon最高", "いや、ヨドバシのほうが最高"]
let oldArticleComment = ArticleComment(contents: comments)
// articleCommentを普通に利用する処理があると仮定
// 他の箇所にArticleCommentを渡したい場合
let newArticleComment = oldArticleComment.clone()
newArticleComment.pushCommentContent(txt: "楽天のほうが良い!")
print(oldArticleComment.fetchCommentContent()) // ["Amazon最高", "いや、ヨドバシのほうが最高"]
print(newArticleComment.fetchCommentContent()) // ["Amazon最高", "いや、ヨドバシのほうが最高", "楽天のほうが良い!"]
// 値渡しなので、newArticleCommentに値を追加しても、oldArticleCommentに影響はない
// 複雑な生成処理を気にしないで良い(例: initに値を渡さなければいけない or 生成の手順などを全く気にしなくて良い
// -> インスタンス化が簡単
総評
- 理解するのは難しくないパターン
- クラスのインスタンスの使い回しなどで活躍できそう
- 他の人がいっていたが、画像描画系などで線のコピーはよくある機能なので、そういったところでも活躍できそう
- チームでやる場合、他の人も読みやすいし、未来の自分も読みやすくなるというメリットもある
- classは普通に扱うと参照渡しになるが、参照渡しは、複雑になったり障害の元になるなど、危険なため、値渡しになるので安全性は高まると思われた
補足
- UIViewControllerの場合は、既にcopyメソッドとmutableCopyメソッドが存在する
- oveerideして使う。overrideしないでcopyメソッドを利用した場合、例外が発生する
import UIKit
class ViewController: UIViewController {
var txt = ""
func setup(txt: String) {
self.txt = txt
}
// https://developer.apple.com/documentation/objectivec/nsobject/1418807-copy
override func copy() -> Any {
let vc = ViewController()
vc.setup(txt: self.txt)
return vc
}
// https://developer.apple.com/documentation/objectivec/nsobject/1418978-mutablecopy
override func mutableCopy() -> Any {
let vc = ViewController()
vc.setup(txt: self.txt)
return vc
}
func shout() -> String {
return self.txt
}
}
let vc = ViewController()
vc.setup(txt: "test1")
let vc2 = vc.mutableCopy() as! ViewController
//let vc2 = vc.copy() as! ViewController
vc2.setup(txt: "test2")
print(vc.shout())
print(vc2.shout())