score:13
What is reification?
Type reification is one of Kotlin's tricks. It happens only in inlined generic functions, if you declare the generic parameter as reified
.
Since it's inlined, the generic parameter can be a concrete class
, instead of just a compile-time type information.
You can do something impossible in Java like:
instanceof
You can now use instanceof
s (in Kotlin, is
s):
inline fun <reified T> f(a: Any) {
if (a is T) println("Hi!")
}
This is obviously impossible in Java.
reflection
You're possible to get the java java.lang.Class<T>
instance from the generic parameter now.
inline fun <reified T> f(a: Any) {
println("Hey! my class is ${T::class.java}!")
if (a.javaClass == T::class.java) println("Hi!")
}
Also, KClass
as well:
inline fun <reified T> f(a: Any) {
println("KClass: ${T::class}")
}
You can create instances with the empty constructor:
inline fun <reified T> f(a: Any) {
val o: T = T::class.java.newInstance()
}
calling other reifieds
Only reified
generic parameter is possible to be passed to other reified
functions.
inline fun <reified T> f(a: Any) {
g<T>(a)
}
inline fun <reified T> g(a: Any) {
if (a is T) println("Bingo!")
}
This is impossible in Kotlin:
inline fun <reified T> f(a: Any) {
}
fun <T> g(a: Any) {
f<T>(a) // error
}
shortcomings (edited)
If you use other languages to invoke a reified
inline function in Kotlin, the function parameter will be java.lang.Object
.
You can't use other languages to invoke a reified
function.
Like, if we have a reified function in A.kt
:
inline fun <reified T> f(a: T) = println(T::class.java)
And get it using reflection (it will be compiled as private):
Method method = AKt.class.getDeclaredMethod("f", Object.class);
This code will successfully run without exceptions.
But you can't invoke it (I didn't read the generated bytecode carefully, sorry) due to it's implementation:
private static final void f(Object a) {
Intrinsics.reifiedOperationMarker(4, "T"); // I didn't see
// the implementation of this line, so I thought it's
// possible to call it in other languages
Class var2 = Object.class;
System.out.println(var2);
}
Look at the comment. And look at the definition of reifiedOperationMarker
:
public static void reifiedOperationMarker(int id, String typeParameterIdentifier) {
throwUndefinedForReified();
}
And it will throw an UnsupportedOperationException
.
Conclusion: reified
can only be used in Kotlin.
about scala
It's really difficult to say whether Kotlin or Scala is better, because Scala's has more ways to get type information at runtime.
Alexey Romanov said that Scala can but Kotlin can't:
using ClassTags in a recursive function
I think this can be solved by using functions inside functions:
inline fun <reified T> g(a: Any): Int {
var recur: ((Any) -> T)? = null
recur = { recur!!.invoke(it) as T } // use T is possible here
return recur(a)
}
Note that this is only an example that syntactically correct.
It's infinite loop and unnecessary cast, of course.
He also said:
storing them in collections and using them to call ClassTag-using functions later.
This is a true problem, because this needs noinline
lambdas, while Kotlin's reified
is based on inline.
score:3
When Kotlin inlines a generic function, it naturally substitutes the type parameters by the type it was called with. E.g. with inline fun <T> foo(x: T) = ...
foo(File("."))
becomes
val x = File(".")
// body of foo with File used everywhere T was
What reified
does is just to allow using operations in body of foo
which will only make sense after this substitution but are illegal for non-reified
type parameters, such as T::class
.
The relevant Scala feature is ClassTag
/TypeTag
, not the "sophisticated type system". Effectively, it automates passing the Class<T>
(or TypeToken<T>
) as an argument, which can be done manually in Java and often is. Note that this is a completely different approach than reified
.
I don't think there's anything which reified
does which isn't possible in Scala, but the advantage of the Kotlin approach is more natural syntax: e.g. in in Scala you can't just write classOf[T]
in a ClassTag
-using method like you would classOf[File]
.
OTOH, Scala allows things which aren't possible with reified
, e.g.:
using
ClassTag
s in a recursive functionstoring them in collections and using them to call
ClassTag
-using functions later.
Source: stackoverflow.com
Related Query
- What does Kotlin's type reification make possible that is not possible in Java or Scala?
- What is the efficient way to create Spark DataFrame in Scala with array type columns from another DataFrame that does not have an array column?
- Why does scalac not believe that a method does not fit the required type signature?
- @throws in Scala does not allow calling Java to catch correct exception type
- Is it possible to implement `??` (a null coalescing operator from C#) in Scala that does not use reflection?
- In what scenario does self-type annotation provide behavior not possible with extends
- Gentle Intro to Haskell: " .... there is no single type that contains both 2 and 'b'." Can I not make such a type ?
- passing a sequence into varargs method that does not use type ascription
- scala type alias to java enum does not work?
- How does the Scala program compile, given that bindAndHandle method takes the first parameter of type Flow not Route?
- What does "method process in class ForeachWriter of type (value: org.apache.spark.sql.Row)Unit is not defined" mean with ForeachWriter?
- What does it mean to say that a method (such as 'react)' does not return?
- What does it mean to say that "unions are currently performed based on location, not on schema"?
- Java Generic Type Converted to Scala does not accept super class itself
- Editor does not contain a main type
- "Parameter type in structural refinement may not refer to an abstract type defined outside that refinement"
- What does :_* do when calling a Java vararg method from Scala?
- What special rules does the scala compiler have for the unit type within the type system
- Why does 2.11.1 fail with error: not found: type Application?
- Why does this compile under Java 7 but not under Java 8?
- What does "reflective access of structural type member method should be enabled..." warning mean in Scala?
- Is it possible to make json4s not to throw exception when required field is missing?
- Type parameter does not extend given type
- What advantages does Ceylon have over Java or Scala
- Why does this Scala function compile when the argument does not conform to the type constraint?
- What advantages does Scala have over Java for concurrent programming?
- What does "no global type inference" mean regarding Scala?
- Intellij: SBT-based Scala project does not build with Java 9
- scala annotation argument needs to be constant but final val does not make it
- Is it possible in Scala to specify a constraint on a generic type τ such that τ <: σ ∧ τ ≠ σ?
More Query from same tag
- Table is not Found while testing with H2Database
- Scala Pattern match on a list with at `@` symbol an extractor
- Scala case class ignoring import in the Spark shell
- Why we need lazy evaluation by extending App trait in Scala?
- Regex on nested arrays?
- What does "ap" of \/ in Scalaz do?
- how to "flatten" the JSon representation of a composite object?
- calling mechanize inside scala failed:HtmlDocument cannot be cast to scala.runtime.Nothin
- How to Encode a bigger JSON dataset to avro?
- DSL in scala using case classes
- Playback historical data Akka Stream
- Replacing a value in nested map
- Can scala abstract type can hold the type parameter?
- Scala: Mocking an enclosed object
- Akka actor does not receive message with DistributedPubSub
- How to catch exceptions and redirect to error page in Lift?
- Most efficient way to search a nested list for a tuple in Scala
- How to pattern match in scala 2.13?
- What is RNA in scala?
- Scala: Using representation types
- Scala: Printing fields and values of given class
- How to use a specific stylesheet for only 1 page in Play
- call simple database procedure using Slick 3.0
- Convert Resulting Rdd into HashMap
- Aggregation Function and Process Function on event time
- Finding character in 2 dimensional scala list
- How do I group Cassandra rows in Scala
- Does Scala's BigDecimal violate the equals/hashCode contract?
- Is there a way to chain two arbitrary specs2 tests (in Scala)?
- Deploy on Heroku using Scalatra