0
# Mirrors and Reflective Operations
1
2
Mirror system providing entry points for reflective operations including instance creation, method invocation, and field access. Mirrors act as the bridge between the symbolic representation of code and actual runtime operations.
3
4
## Capabilities
5
6
### Base Mirror API
7
8
Core mirror functionality providing symbol resolution and reflective access.
9
10
```scala { .api }
11
/**
12
* Base mirror providing symbol resolution and basic reflection capabilities
13
*/
14
trait MirrorApi { this: Mirror =>
15
/** Get the universe this mirror belongs to */
16
def universe: Universe
17
18
/** Convert a runtime class to a class symbol */
19
def classSymbol(rtcls: RuntimeClass): ClassSymbol
20
21
/** Convert a class symbol to a runtime class */
22
def runtimeClass(cls: ClassSymbol): RuntimeClass
23
24
/** Convert a module symbol to a runtime class */
25
def runtimeClass(mod: ModuleSymbol): RuntimeClass
26
}
27
```
28
29
### Reflective Mirror
30
31
Extended mirror providing comprehensive reflection capabilities.
32
33
```scala { .api }
34
/**
35
* Reflective mirror providing comprehensive reflection operations
36
*/
37
trait ReflectiveMirror extends MirrorApi {
38
/** Create an instance mirror for runtime operations on objects */
39
def reflect(obj: Any): InstanceMirror
40
41
/** Create a class mirror for static operations and construction */
42
def reflectClass(cls: ClassSymbol): ClassMirror
43
44
/** Create a module mirror for singleton object access */
45
def reflectModule(mod: ModuleSymbol): ModuleMirror
46
}
47
```
48
49
### Instance Mirror
50
51
Mirror for performing operations on object instances.
52
53
```scala { .api }
54
/**
55
* Instance mirror for runtime operations on object instances
56
*/
57
trait InstanceMirrorApi { this: InstanceMirror =>
58
/** The instance being reflected upon */
59
def instance: Any
60
61
/** Symbol of the instance's class */
62
def symbol: ClassSymbol
63
64
/** Create a method mirror for invoking instance methods */
65
def reflectMethod(method: MethodSymbol): MethodMirror
66
67
/** Create a field mirror for accessing instance fields */
68
def reflectField(field: TermSymbol): FieldMirror
69
70
/** Create a class mirror for the instance's class */
71
def reflectClass: ClassMirror
72
}
73
```
74
75
**Usage Example:**
76
77
```scala
78
import scala.reflect.runtime.universe._
79
import scala.reflect.runtime.{currentMirror => cm}
80
81
class Calculator {
82
var result: Double = 0.0
83
def add(x: Double, y: Double): Double = {
84
result = x + y
85
result
86
}
87
def getResult: Double = result
88
}
89
90
val calc = new Calculator
91
val instanceMirror = cm.reflect(calc)
92
93
// Method invocation
94
val addMethod = typeOf[Calculator].decl(TermName("add")).asMethod
95
val addMirror = instanceMirror.reflectMethod(addMethod)
96
val sum = addMirror(10.0, 5.0)
97
println(s"Sum: $sum")
98
99
// Field access
100
val resultField = typeOf[Calculator].decl(TermName("result")).asTerm
101
val fieldMirror = instanceMirror.reflectField(resultField)
102
println(s"Current result: ${fieldMirror.get}")
103
104
// Field modification
105
fieldMirror.set(100.0)
106
println(s"Modified result: ${fieldMirror.get}")
107
```
108
109
### Method Mirror
110
111
Mirror for invoking methods reflectively.
112
113
```scala { .api }
114
/**
115
* Method mirror for reflective method invocation
116
*/
117
trait MethodMirrorApi { this: MethodMirror =>
118
/** Symbol of the method being reflected */
119
def symbol: MethodSymbol
120
121
/** Invoke the method with given arguments */
122
def apply(args: Any*): Any
123
124
/** The receiver instance (for instance methods) */
125
def receiver: Any
126
}
127
```
128
129
**Usage Example:**
130
131
```scala
132
import scala.reflect.runtime.universe._
133
import scala.reflect.runtime.{currentMirror => cm}
134
135
case class Person(firstName: String, lastName: String) {
136
def fullName: String = s"$firstName $lastName"
137
def greet(greeting: String, name: String): String = s"$greeting $name, I'm ${fullName}"
138
}
139
140
val person = Person("Alice", "Smith")
141
val instanceMirror = cm.reflect(person)
142
143
// Method with no parameters
144
val fullNameMethod = typeOf[Person].decl(TermName("fullName")).asMethod
145
val fullNameMirror = instanceMirror.reflectMethod(fullNameMethod)
146
val name = fullNameMirror()
147
println(s"Full name: $name")
148
149
// Method with parameters
150
val greetMethod = typeOf[Person].decl(TermName("greet")).asMethod
151
val greetMirror = instanceMirror.reflectMethod(greetMethod)
152
val greeting = greetMirror("Hello", "Bob")
153
println(s"Greeting: $greeting")
154
```
155
156
### Field Mirror
157
158
Mirror for accessing and modifying fields reflectively.
159
160
```scala { .api }
161
/**
162
* Field mirror for reflective field access and modification
163
*/
164
trait FieldMirrorApi { this: FieldMirror =>
165
/** Symbol of the field being reflected */
166
def symbol: TermSymbol
167
168
/** Get the current value of the field */
169
def get: Any
170
171
/** Set the field to a new value (for vars only) */
172
def set(value: Any): Unit
173
174
/** The receiver instance */
175
def receiver: Any
176
177
/** Check if this field is settable (var) */
178
def isSettable: Boolean
179
}
180
```
181
182
**Usage Example:**
183
184
```scala
185
import scala.reflect.runtime.universe._
186
import scala.reflect.runtime.{currentMirror => cm}
187
188
class Counter {
189
var count: Int = 0
190
val name: String = "MyCounter"
191
192
def increment(): Unit = count += 1
193
}
194
195
val counter = new Counter
196
val instanceMirror = cm.reflect(counter)
197
198
// Access var field
199
val countField = typeOf[Counter].decl(TermName("count")).asTerm
200
val countMirror = instanceMirror.reflectField(countField)
201
202
println(s"Initial count: ${countMirror.get}")
203
countMirror.set(10)
204
println(s"Modified count: ${countMirror.get}")
205
206
// Access val field
207
val nameField = typeOf[Counter].decl(TermName("name")).asTerm
208
val nameMirror = instanceMirror.reflectField(nameField)
209
println(s"Counter name: ${nameMirror.get}")
210
211
// Check if settable
212
println(s"Count is settable: ${countMirror.isSettable}")
213
println(s"Name is settable: ${nameMirror.isSettable}")
214
```
215
216
### Class Mirror
217
218
Mirror for class-level operations like construction.
219
220
```scala { .api }
221
/**
222
* Class mirror for static operations and object construction
223
*/
224
trait ClassMirrorApi { this: ClassMirror =>
225
/** Symbol of the class being reflected */
226
def symbol: ClassSymbol
227
228
/** Create a constructor mirror for object instantiation */
229
def reflectConstructor(constructor: MethodSymbol): MethodMirror
230
231
/** Create a module mirror for the companion object */
232
def companion: ModuleMirror
233
234
/** The runtime class */
235
def runtimeClass: RuntimeClass
236
}
237
```
238
239
**Usage Example:**
240
241
```scala
242
import scala.reflect.runtime.universe._
243
import scala.reflect.runtime.{currentMirror => cm}
244
245
case class Book(title: String, author: String, pages: Int)
246
247
// Get class mirror
248
val bookClass = typeOf[Book].typeSymbol.asClass
249
val classMirror = cm.reflectClass(bookClass)
250
251
// Find primary constructor
252
val constructor = bookClass.primaryConstructor.asMethod
253
val constructorMirror = classMirror.reflectConstructor(constructor)
254
255
// Create new instance
256
val book = constructorMirror("Scala in Depth", "Joshua Suereth", 304).asInstanceOf[Book]
257
println(s"Created book: $book")
258
259
// Alternative: find constructor by parameter types
260
val constructors = bookClass.info.members.filter(_.isConstructor).map(_.asMethod)
261
constructors.foreach { ctor =>
262
println(s"Constructor: ${ctor.name} -> ${ctor.paramLists}")
263
}
264
```
265
266
### Module Mirror
267
268
Mirror for accessing singleton objects.
269
270
```scala { .api }
271
/**
272
* Module mirror for singleton object access
273
*/
274
trait ModuleMirrorApi { this: ModuleMirror =>
275
/** Symbol of the module being reflected */
276
def symbol: ModuleSymbol
277
278
/** Get the singleton instance */
279
def instance: Any
280
281
/** Create an instance mirror for the singleton object */
282
def reflect: InstanceMirror
283
}
284
```
285
286
**Usage Example:**
287
288
```scala
289
import scala.reflect.runtime.universe._
290
import scala.reflect.runtime.{currentMirror => cm}
291
292
object MathUtils {
293
def add(x: Int, y: Int): Int = x + y
294
def multiply(x: Int, y: Int): Int = x * y
295
val PI: Double = 3.14159
296
}
297
298
// Get module mirror
299
val mathUtilsModule = cm.staticModule("MathUtils")
300
val moduleMirror = cm.reflectModule(mathUtilsModule)
301
302
// Get singleton instance
303
val mathUtilsInstance = moduleMirror.instance
304
println(s"Module instance: $mathUtilsInstance")
305
306
// Reflect on the instance
307
val instanceMirror = moduleMirror.reflect
308
309
// Call methods on the object
310
val addMethod = mathUtilsModule.info.decl(TermName("add")).asMethod
311
val addMirror = instanceMirror.reflectMethod(addMethod)
312
val sum = addMirror(3, 4)
313
println(s"3 + 4 = $sum")
314
315
// Access fields
316
val piField = mathUtilsModule.info.decl(TermName("PI")).asTerm
317
val piMirror = instanceMirror.reflectField(piField)
318
println(s"PI = ${piMirror.get}")
319
```
320
321
### Complete Reflection Workflow
322
323
Comprehensive example showing the complete reflection workflow.
324
325
```scala
326
import scala.reflect.runtime.universe._
327
import scala.reflect.runtime.{currentMirror => cm}
328
329
// Example class hierarchy
330
abstract class Animal(val name: String) {
331
def speak: String
332
def age: Int = 0
333
}
334
335
class Dog(name: String, val breed: String) extends Animal(name) {
336
override def speak: String = "Woof!"
337
override def age: Int = 3
338
def wagTail(): String = s"$name is wagging tail"
339
}
340
341
object AnimalShelter {
342
def adoptAnimal(animal: Animal): String = s"${animal.name} has been adopted!"
343
}
344
345
// 1. Runtime type inspection
346
val dogType = typeOf[Dog]
347
println(s"Dog type: $dogType")
348
println(s"Base classes: ${dogType.baseClasses.map(_.name)}")
349
350
// 2. Create instance using reflection
351
val dogClass = dogType.typeSymbol.asClass
352
val classMirror = cm.reflectClass(dogClass)
353
val constructor = dogClass.primaryConstructor.asMethod
354
val constructorMirror = classMirror.reflectConstructor(constructor)
355
val dog = constructorMirror("Buddy", "Golden Retriever").asInstanceOf[Dog]
356
357
println(s"Created dog: $dog")
358
359
// 3. Instance reflection
360
val dogInstanceMirror = cm.reflect(dog)
361
362
// 4. Field access
363
val nameField = dogType.baseClasses
364
.map(_.info)
365
.find(_.decl(TermName("name")) != NoSymbol)
366
.get.decl(TermName("name")).asTerm
367
val nameFieldMirror = dogInstanceMirror.reflectField(nameField)
368
println(s"Dog name: ${nameFieldMirror.get}")
369
370
val breedField = dogType.decl(TermName("breed")).asTerm
371
val breedFieldMirror = dogInstanceMirror.reflectField(breedField)
372
println(s"Dog breed: ${breedFieldMirror.get}")
373
374
// 5. Method invocation
375
val speakMethod = dogType.decl(TermName("speak")).asMethod
376
val speakMirror = dogInstanceMirror.reflectMethod(speakMethod)
377
println(s"Dog says: ${speakMirror()}")
378
379
val wagTailMethod = dogType.decl(TermName("wagTail")).asMethod
380
val wagTailMirror = dogInstanceMirror.reflectMethod(wagTailMethod)
381
println(s"Action: ${wagTailMirror()}")
382
383
// 6. Object reflection
384
val shelterModule = cm.staticModule("AnimalShelter")
385
val shelterModuleMirror = cm.reflectModule(shelterModule)
386
val shelterInstanceMirror = shelterModuleMirror.reflect
387
388
val adoptMethod = shelterModule.info.decl(TermName("adoptAnimal")).asMethod
389
val adoptMirror = shelterInstanceMirror.reflectMethod(adoptMethod)
390
println(s"Adoption: ${adoptMirror(dog)}")
391
```
392
393
### Error Handling in Reflective Operations
394
395
Common exceptions and error handling patterns:
396
397
```scala
398
import scala.reflect.runtime.universe._
399
import scala.reflect.runtime.{currentMirror => cm}
400
import scala.util.{Try, Success, Failure}
401
402
def safeReflectiveCall[T](operation: => T): Try[T] = {
403
Try(operation).recover {
404
case _: ScalaReflectionException =>
405
println("Reflection operation failed")
406
throw new RuntimeException("Reflection error")
407
case _: IllegalArgumentException =>
408
println("Invalid arguments provided")
409
throw new RuntimeException("Argument error")
410
case _: IllegalAccessException =>
411
println("Access denied")
412
throw new RuntimeException("Access error")
413
}
414
}
415
416
// Safe method invocation
417
class TestClass {
418
def publicMethod(): String = "public"
419
private def privateMethod(): String = "private"
420
}
421
422
val testInstance = new TestClass
423
val instanceMirror = cm.reflect(testInstance)
424
425
// This will succeed
426
safeReflectiveCall {
427
val method = typeOf[TestClass].decl(TermName("publicMethod")).asMethod
428
val methodMirror = instanceMirror.reflectMethod(method)
429
methodMirror()
430
} match {
431
case Success(result) => println(s"Success: $result")
432
case Failure(ex) => println(s"Failed: ${ex.getMessage}")
433
}
434
435
// This may fail (accessing private method)
436
safeReflectiveCall {
437
val method = typeOf[TestClass].decl(TermName("privateMethod")).asMethod
438
val methodMirror = instanceMirror.reflectMethod(method)
439
methodMirror()
440
} match {
441
case Success(result) => println(s"Success: $result")
442
case Failure(ex) => println(s"Failed: ${ex.getMessage}")
443
}
444
```