Swiftはリフレクションをサポートしていますか?例えばSwiftオブジェクトのvalueForKeyPath:
やsetValue:forKeyPath:
のようなものはありますか?
実際、Objective-Cのobj.class
のような動的型システムさえありますか?
いくつかのリフレクションサポートの開始があるようです。
class Fruit {
var name="Apple"
}
reflect(Fruit()).count // 1
reflect(Fruit())[0].0 // "name"
reflect(Fruit())[0].1.summary // "Apple"
Mchambers Gistから、ここ: https://Gist.github.com/mchambers/fb9da554898dae3e54f2
クラスがNSObject
を拡張する場合、Objective-Cのイントロスペクションとダイナミズムはすべて機能します。これも:
この機能の欠点の1つは、Swiftオプション値タイプのサポートです。たとえば、Intプロパティは列挙および変更できますが、Int?プロパティはできません。オプションの型は、reflect/MirrorTypeを使用して部分的に列挙できますが、変更することはできません。
クラスがNSObject
を拡張しない場合、新しい、非常に限定された(進行中の)リフレクションのみが機能します(reflect/MirrorTypeを参照)。これにより、クラスとプロパティについてインスタンスに問い合わせる制限された機能が追加されますが、なし上記の追加機能の。
NSObjectを拡張しない場合、または '@objc'ディレクティブを使用する場合、Swiftはデフォルトで静的およびvtableベースのディスパッチになります。これは高速ですが、仮想マシンがない場合、ランタイムメソッドのインターセプトは許可されません。このインターセプトはCocoaの基本的な部分であり、次のタイプの機能に必要です。
したがって、Swiftで実装されたCocoa/CocoaTouchアプリケーションのクラスを推奨します。
概要:
参照データ:メソッド呼び出しの実行オーバーヘッド:
(実際のパフォーマンスはハードウェアに依存しますが、比率は同じままです)。
また、動的属性により、メソッドが動的ディスパッチを使用する必要があることを明示的にSwiftに指示できるため、インターセプトがサポートされます。
public dynamic func foobar() -> AnyObject {
}
ドキュメントは、主に約動的型システムについて語っています
Type
およびdynamicType
メタデータタイプ(言語リファレンス) を参照してください
例:
var clazz = TestObject.self
var instance: TestObject = clazz()
var type = instance.dynamicType
println("Type: \(type)") //Unfortunately this prints only "Type: Metatype"
TestObject
がNSObject
を拡張すると仮定します
var clazz: NSObject.Type = TestObject.self
var instance : NSObject = clazz()
if let testObject = instance as? TestObject {
println("yes!") //prints "yes!"
}
現在、実装されているリフレクションはありません。
編集: 私は明らかに間違っていた、ステベックスの答えを参照してください。おそらくIDEがオブジェクトの内容を検査できるようにするために、プロパティビルドにいくつかの単純な読み取り専用リフレクションがあります。
SwiftリフレクションAPIは、現時点ではAppleの優先度が高くないようです。しかし、@ stevex answer に加えて、標準ライブラリに役立つ別の関数があります。
ベータ6以降、_stdlib_getTypeName
は変数のマングル型名を取得します。これを空の遊び場に貼り付けます。
import Foundation
class PureSwiftClass {
}
var myvar0 = NSString() // Objective-C class
var myvar1 = PureSwiftClass()
var myvar2 = 42
var myvar3 = "Hans"
println( "TypeName0 = \(_stdlib_getTypeName(myvar0))")
println( "TypeName1 = \(_stdlib_getTypeName(myvar1))")
println( "TypeName2 = \(_stdlib_getTypeName(myvar2))")
println( "TypeName3 = \(_stdlib_getTypeName(myvar3))")
出力は次のとおりです。
TypeName0 = NSString
TypeName1 = _TtC13__lldb_expr_014PureSwiftClass
TypeName2 = _TtSi
TypeName3 = _TtSS
Ewan Swickのブログエントリ は、これらの文字列の解読に役立ちます。
例えば_TtSi
は、Swiftの内部Int
タイプを表します。
代わりにtoString()を使用することを検討してください。これはパブリックであり、_ stdlib_getTypeName()と同じように機能しますが、AnyClassでも機能する点が異なります。遊び場で
class MyClass {}
toString(MyClass.self) // evaluates to "__lldb_expr_49.MyClass"