score:15
Based on what soc wrote, I got this:
import scala.reflect.runtime.universe._
val members = typeOf[MyClass].members.filter(_.typeSignature match {
case tpe if tpe <:< typeOf[ThirdParty] => true
case NullaryMethodType(tpe) if tpe <:< typeOf[ThirdParty] => true
case MethodType(Nil, tpe) if tpe <:< typeOf[ThirdParty] => true
case _ => false
})
Let me explain the pattern match. The type of a val
or an object
can be compared directly, but functions have a slightly different type. Here I'm matching against methods with no parameter lists, and methods with a zero-arity parameter list.
There are some differences here compared to soc's answer. First, I use members
instead of declarations
. That returns inherited members as well as those that are declared on MyClass
itself.
Second, I check that it is a value member, as opposed to a type member. You can only invoke methods on values, so it looked a reasonable restriction, though maybe unnecessary. upd. The isValue
method is no longer available in 2.10.0-RC1, so I removed the check.
Finally, I use <:<
instead of checking each parent for equality.
Now, to the invocation. I'm going to change the code above since invocation depends on what kind of member you have, so we'd best do filtering and invocation at the same time. I'm going to change from members
to nonPrivateMembers
as well, assuming that's what is wanted. upd. nonPrivateMembers
is no longer available in 2.10.0-RC1, use filter(!_.isPrivate)
if necessary.
And I'll also avoid using typeOf
, which won't work with mirrors on the REPL. upd. In 2.10.0-RC1 typeOf
is working finely, but I'll keep the skeleton of the implementation unchanged.
All of the above is basically concerned with the structure of things: what the members of a type are, what kind of members they are, and so on. When you want to use this stuff, in you need mirrors.
Whenever you have a symbol or a type for something -- a class, method, obj, etc -- you act on that thing through a mirror. To act (reflectively) on an instance of an object, you need an instance mirror. To act on a method, you need a method mirror, and so on.
So let's try to build a functon to do what's requested:
import scala.reflect.runtime.universe._
def invoke[Target : TypeTag](obj: Any): Seq[Target] = {
val mirror = runtimeMirror(obj.getClass.getClassLoader)
val insMirror = mirror reflect obj
val originType = insMirror.symbol.typeSignature
val targetType = typeTag[Target].tpe
val members = originType.members
val result = members collect (member => member.typeSignature match {
case tpe if tpe <:< typeOf[ThirdParty] =>
if (member.isModule)
(insMirror reflectModule member.asModule).instance
else
(insMirror reflectField member.asTerm).get
case NullaryMethodType(tpe) if tpe <:< typeOf[ThirdParty] =>
(insMirror reflectMethod member.asMethod).apply()
case MethodType(Nil, tpe) if tpe <:< typeOf[ThirdParty] =>
(insMirror reflectMethod member.asMethod).apply()
})
result.map(_.asInstanceOf[Target]).toSeq
}
Note that nested modules cannot be recovered with Scala 2.10.0-M4 -- that should be possible with M5 or RC1. To test this code with M4, replace the module code with null
.
Here's a sample:
scala> class MyClass {
object objA extends ThirdParty
object objB extends WeatherIcon
val aVal = new ThirdParty {}
val bVal = new WeatherIcon {}
def aDef = new ThirdParty {}
def bDef = new WeatherIcon {}
def anotherDef() = new ThirdParty {}
def yetAnotherDef() = new WeatherIcon {}
}
defined class MyClass
scala> invoke[ThirdParty](new MyClass)
res88: Seq[ThirdParty] = List(MyClass$$anon$5@c250cba, MyClass$$anon$3@54668d90, MyClass$$anon$1@18d8143a, null)
score:2
I can't offer a complete solution, but maybe this is a start:
import reflect.runtime.universe._
val myClassType = typeOf[MyClass] // Get the type of McClass
val thirdPartyType = typeOf[ThirdParty] // Get the type of ThirdParty
val methodToInvoke = newTermName("invoke")
val declsOfMyClass = myClassType.declarations // Get the declarations of MyClass
val subtypesOfThirdParty =
declsOfMyClass.filter(_.typeSignature.parents.contains(thirdPartyType))
val methodsToInvoke = // Now we have the methods.
subtypesOfThirdParty.map(tps => tps.typeSignature.member(methodToInvoke))
// TODO: Invoke!
I guess there is a much more straight-forward way than this.
Source: stackoverflow.com
Related Query
- How to use scala reflection API to get all contained classes
- Get all the classes that implements a trait in Scala using reflection
- Scala - how to get the 'type' for a field using reflection api
- How do I use Scala reflection to find all subclasses of a trait (without using third-party tools)?
- How can I use Scala reflection to get only primary constructor parameters?
- How to get underlying constant type from singleton type with Scala reflection API
- How can I use scopt in Scala to get all of the remaining arguments?
- How do I use Scala reflection to get a property from a method annotation
- Scala type keyword: how best to use it across multiple classes
- How to use Scala in IntelliJ IDEA (or: why is it so difficult to get a working IDE for Scala)?
- Get companion object instance with new Scala reflection API
- How to get all request parameters in Play and Scala
- How to use Scala 2.10 implicit classes
- How to use my classes from Scala worksheet in IntelliJ CE with Scala plugin?
- How do I use Scala dispatch to get the URL returned in a 301 redirect?
- How can I get all object vals and subobject vals using reflection in Scala?
- Get the companion object instance of a inner modul with the Scala reflection API
- scala: how to create a generic type which is subtype of all the number classes in scala so that it can include compare method
- How can I use the new reflection API to tell if the component type of an array conforms to a type parameter?
- How does Scala use all my cores here?
- How to use JSR-223 to get Scala interpreter in sbt console?
- How can I get random data generated for scala case classes with the ability to "change some values" for unit testing?
- How to get name of all methods in a scala trait
- How to make full use of all cores using Scala actors?
- Scala recursive API calls to get all the results
- How to use path-dependent types with type classes in Scala
- How to get Intellij to use dependencies from SBT scala
- How can I import all unimported classes in Scala IDE?
- How to use Scala Enumerations in Classes
- How can I get all (non-final) object vals and subobject vals using reflection in Scala?
More Query from same tag
- Extracting numbers in 9+.9* format from text with Scala regex
- Ammonite: how to use another script from an Ivy dependency?
- Type variance in multiple type instances of traits
- Scala Play messages file to inline or reuse the version in build.sbt
- Is there any possibility of spark.scheduler.pool (local property ) set from spark-submit
- Mongodb scala driver codec for trait and inherited classes
- Error in using spark-cassandra-connector: java.lang.NoSuchMethodError
- Writing JSON depending on instance type
- Scala - Passing function as parameter when function is overloaded
- Specify plugins in Build.scala
- grpc protocol buffer client returns Jetty ALPN/NPN error
- sbt different libraryDependencies in test than in normal mode
- How can I write a Scalatest test to match the values in a list against a range?
- Syntax error on topology.py when I try to run scala command in spark through Cloudera VM
- Slick codeGenerator does not fill foreignKey names causing assertion failed: duplicate foreign key names detected
- How to get Unique list of string from the columns?
- Throwing always the same exception instance in Java
- Access to WrappedArray elements
- Scala parsing package isn't recognized
- Avoid query parameters duplication when generating a MAC for requests in gatling
- How to construct a NodeSeq programmatically?
- How to Use both Scala and Python in a same Spark project?
- Scala compiler is complaining about type mismatch for generic parameter on method level
- Why is the queue size of a ScheduledThreadPoolExecutor always 0?
- Akka Http retrieve a string value with help of Segment PathMatcher
- How to implement sort logic ascending order on 4 columns
- how to replace letters in a string in alphabetical order
- Akka Stream dynamic Sink depending on Message from Kafka topic
- Why does IntelliJ seem to import my scala libraries twice?
- Calculate Mean value per each category using scala and spark