Kotlin
प्रतिबिंब
खोज…
परिचय
परावर्तन एक भाषा की क्षमता संकलन समय के बजाय रनटाइम पर कोड का निरीक्षण करने की क्षमता है।
टिप्पणियों
परावर्तन, रनटाइम पर भाषा निर्माणों (कक्षाओं और कार्यों) को आत्मसात करने की एक प्रणाली है।
JVM प्लेटफॉर्म को लक्षित करते समय, रनटाइम रिफ्लेक्शन फीचर अलग JAR: kotlin-reflect.jar
में वितरित किए kotlin-reflect.jar
। यह रनटाइम आकार को कम करने, अप्रयुक्त सुविधाओं को काटने और अन्य (जैसे जेएस) प्लेटफार्मों को लक्षित करना संभव बनाता है।
एक वर्ग को संदर्भित करना
KClass
ऑब्जेक्ट का संदर्भ प्राप्त करने के लिए कुछ वर्ग डबल कॉलन का उपयोग करते हैं:
val c1 = String::class
val c2 = MyClass::class
एक समारोह का संदर्भ लेना
कोटलिन में फ़ंक्शंस प्रथम श्रेणी के नागरिक हैं। आप दोहरे कॉलनों का उपयोग करके इस पर एक संदर्भ प्राप्त कर सकते हैं और फिर इसे किसी अन्य फ़ंक्शन में पास कर सकते हैं:
fun isPositive(x: Int) = x > 0
val numbers = listOf(-2, -1, 0, 1, 2)
println(numbers.filter(::isPositive)) // [1, 2]
जावा प्रतिबिंब के साथ इंटर-संचालन
एक जावा के प्राप्त करने के लिए Class
Kotlin से वस्तु KClass
का उपयोग .java
विस्तार संपत्ति:
val stringKClass: KClass<String> = String::class
val c1: Class<String> = stringKClass.java
val c2: Class<MyClass> = MyClass::class.java
बाद के उदाहरण को संकलक द्वारा अनुकूलित किया जाएगा एक मध्यवर्ती KClass
उदाहरण आवंटित नहीं करने के लिए।
एक वर्ग के सभी गुणों के मूल्यों को प्राप्त करना
कुछ गुणों के साथ BaseExample
वर्ग का विस्तार करने BaseExample
Example
वर्ग दिया गया:
open class BaseExample(val baseField: String)
class Example(val field1: String, val field2: Int, baseField: String):
BaseExample(baseField) {
val field3: String
get() = "Property without backing field"
val field4 by lazy { "Delegated value" }
private val privateField: String = "Private value"
}
एक वर्ग के सभी गुणों को पकड़ सकता है:
val example = Example(field1 = "abc", field2 = 1, baseField = "someText")
example::class.memberProperties.forEach { member ->
println("${member.name} -> ${member.get(example)}")
}
इस कोड को चलाने से अपवाद को फेंक दिया जाएगा। प्रॉपर्टी private val privateField
को निजी घोषित किया जाता है और उस पर कॉलिंग member.get(example)
सफल नहीं होगा। निजी संपत्तियों को छानने के लिए इसे संभालने का एक तरीका। ऐसा करने के लिए हमें किसी संपत्ति के जावा गेट्टर के दृश्यता संशोधक की जांच करनी होगी। private val
के मामले में private val
मौजूद नहीं है, इसलिए हम निजी पहुंच ग्रहण कर सकते हैं।
सहायक कार्य और इसका उपयोग इस तरह हो सकता है:
fun isFieldAccessible(property: KProperty1<*, *>): Boolean {
return property.javaGetter?.modifiers?.let { !Modifier.isPrivate(it) } ?: false
}
val example = Example(field1 = "abc", field2 = 1, baseField = "someText")
example::class.memberProperties.filter { isFieldAccessible(it) }.forEach { member ->
println("${member.name} -> ${member.get(example)}")
}
एक अन्य दृष्टिकोण प्रतिबिंब का उपयोग करके निजी संपत्तियों को सुलभ बनाना है:
example::class.memberProperties.forEach { member ->
member.isAccessible = true
println("${member.name} -> ${member.get(example)}")
}
किसी वर्ग के सभी गुणों का मान निर्धारित करना
एक उदाहरण के रूप में हम एक नमूना वर्ग के सभी स्ट्रिंग गुण सेट करना चाहते हैं
class TestClass {
val readOnlyProperty: String
get() = "Read only!"
var readWriteString = "asd"
var readWriteInt = 23
var readWriteBackedStringProperty: String = ""
get() = field + '5'
set(value) { field = value + '5' }
var readWriteBackedIntProperty: Int = 0
get() = field + 1
set(value) { field = value - 1 }
var delegatedProperty: Int by TestDelegate()
private var privateProperty = "This should be private"
private class TestDelegate {
private var backingField = 3
operator fun getValue(thisRef: Any?, prop: KProperty<*>): Int {
return backingField
}
operator fun setValue(thisRef: Any?, prop: KProperty<*>, value: Int) {
backingField += value
}
}
}
उत्परिवर्तनीय गुण प्राप्त करने से सभी गुण प्राप्त होते हैं, प्रकार से उत्परिवर्तनीय गुणों को छानते हैं। हमें दृश्यता की जांच करने की भी आवश्यकता है, क्योंकि निजी संपत्तियों को पढ़ने से रन टाइम अपवाद होता है।
val instance = TestClass()
TestClass::class.memberProperties
.filter{ prop.visibility == KVisibility.PUBLIC }
.filterIsInstance<KMutableProperty<*>>()
.forEach { prop ->
System.out.println("${prop.name} -> ${prop.get(instance)")
}
सभी String
गुणों को "Our Value"
सेट करने के लिए हम अतिरिक्त रूप से रिटर्न प्रकार से फ़िल्टर कर सकते हैं। चूंकि कोटलिन जावा वीएम पर आधारित है, टाइप एरासुर प्रभाव में है, और इस प्रकार List<String>
जैसे जेनेरिक प्रकारों को लौटाने वाले गुण List<Any>
। अफसोस की बात है कि प्रतिबिंब एक सुनहरी गोली नहीं है और इससे बचने का कोई समझदार तरीका नहीं है, इसलिए आपको अपने उपयोग के मामलों को देखने की जरूरत है।
val instance = TestClass()
TestClass::class.memberProperties
.filter{ prop.visibility == KVisibility.PUBLIC }
// We only want strings
.filter{ it.returnType.isSubtypeOf(String::class.starProjectedType) }
.filterIsInstance<KMutableProperty<*>>()
.forEach { prop ->
// Instead of printing the property we set it to some value
prop.setter.call(instance, "Our Value")
}