私がクラス番号を持っていると想像してください:
class Number {
var val: Double?
}
そして、そのクラスの2つのインスタンスがA
ありB
ます。今、私が次のようなステートメントを通じてマージB
したいと想像A
してください
merge(B, into: A)
もちろん、次のような関数を書くことができます。
func merge(from: Number, into: Number){
into.val = from.val
}
しかし、それはまったく再利用できません。汎用マージクラスを作成する方法はありますか?
更新:いくつかの回答は優れた実行可能な解決策を提供しますが、それらのどれも十分に「一般的」ではありません(ここでの一般的は非技術的な方法で意味されます)それで答えを見て、私はいくつかのインスピレーションを得ました、そしてここに解決策があります現在検討中です。NumberをNSObjectサブクラスにし、マージできるすべてのプロパティを動的として宣言します。例えば:
class Number: NSObject {
//Put the required init and initWithCoder: here
dynamic var val: Double?
}
次に、マージ可能なクラスが尊重しなければならないプロトコルを宣言します
protocol Mergeable: class {
var mergeablePropertyKeys:[String] {get}
}
次に、マージを実行するグローバル関数を宣言します。
func merge<U: Mergeable, Mergeable where U.Type == V.Type>(from: U, into:V){
for property in U.mergeablePropertyKeys {
V.setValue(U.valueForKey(property), property)
}
}
そして、マージする引数が必ずしもそうではないので、これが機能しないことを私は知っていNSObjects
ます。
merge
が両方であることを確認するにはどうすればよいですかNSObjects?
必要なのは、リフレクションを使用してプロパティをマージする汎用関数のようです。Swiftでは反射が制限されていますが、MirrorTypeを使用して実行できます。私は以前にこのメソッドを使用して、一般的なjsonパーサーをswiftで構築しました-同様のことを行うことができますが、json辞書をプロパティに解析する代わりに、2つのオブジェクトのプロパティをマップします。
リフレクションを使用してこれを迅速に行う例:
func merge<T>(itemToMerge:T) {
let mirrorSelf = Mirror(reflecting: self)
let mirrorItemToMerge = Mirror(reflecting: itemToMerge)
for mirrorSelfItem in mirrorSelf.children {
// Loop through items in mirrorItemToMerge.
for mirrorImageItem in mirrorItemToMerge.children {
// If you have a parameter who's name is a match, map the value
// OR You could add any custom mapping logic you need for your specific use case
if mirrorSelfItem.label == mirrorImageItem.label {
// To set values, use self.setValue(valueToSet, forKey: propertyName)
self.setValue(mirrorImageItem.value as? AnyObject, forKey: mirrorImageItem.label!)
}
}
}
}
これは、マージメソッドを定義するオブジェクトがNSObjectのサブクラスであることを前提としています(したがって、NSKeyValueCodingを利用できます)。これを静的メソッドにして、任意のNSObjectタイプの任意の2つのオブジェクトをマージすることもできます。
static func merge<T1: NSObject, T2: NSObject>(itemChanging:T1, itemToMerge:T2) {
let mirrorSelf = Mirror(reflecting: itemChanging)
let mirrorItemToMerge = Mirror(reflecting: itemToMerge)
for mirrorSelfItem in mirrorSelf.children {
// Loop through items in mirrorItemToMerge.
for mirrorImageItem in mirrorItemToMerge.children {
// If you have a parameter who's name is a match, map the value
// OR You could add any custom mapping logic you need for your specific use case
if mirrorSelfItem.label == mirrorImageItem.label {
// To set values, use self.setValue(valueToSet, forKey: propertyName)
self.setValue(mirrorImageItem.value as? AnyObject, forKey: mirrorImageItem.label!)
}
}
}
}
この記事はインターネットから収集されたものであり、転載の際にはソースを示してください。
侵害の場合は、連絡してください[email protected]
コメントを追加