This Question is Answered

2 "helpful" answers available (2 pts)
3 Replies Last post: Feb 19, 2013 1:58 PM by Evgeny Gerashchenko  
Dimitar Dimitrov Newbie 74 posts since
Apr 19, 2006
Currently Being Moderated

Feb 19, 2013 12:49 PM

Class Literals

As a learning exercise, I am porting an existing project from statically typed Groovy to Kotlin.

 

I am struggling to translate the following idiom:

 

 

@CompileStatic class Entity {
    private final Map<Class<? extends Facet>, Facet> facets = [:]
 
    public LogEntity addFacet(Facet facet) {
        def type = facet.getClass() as Class<? extends Facet>
        facets[type] = facet
        return this
    }
 
    public <T extends Facet> T facet(Class<T> facetType) {
        def f = facets[facetType]
        return facetType.cast(f) as T // TODO: GROOVY-5891
    }
}
 
 
// usage
def e = new Entity()
s.addFacet(new SomeData(x: 123, y: 345, ...))
s.addFacet(new SomeOtherData(a: 'abc', b: 123...))
....
 
assert e.facet(SomeData)?.x==123 && e.facet(SomeOtherData)?.a=='abc'

 

And in Kotlin:

 

 

class Entity() {
    val facets : MutableMap<Class<Facet>, Facet> = hashMapOf()
 
    fun setFacet(facet: Facet) : LogEntity {
        facets[facet.javaClass] = facet
        return this
    }
 
    fun <T: Facet> facet(facet: Class<T>) : T? {
        return facet.cast(facets[facet])
    }
}
 
 
// usage
val e = Entity()
s.addFacet(SomeData(123, 345, ...)) // can we have named arguments?
s.addFacet(SomeOtherData('abc', 123...))
 
 
e.facet( ??? )
 

 

 

What we achieve that an entity can contain multiple facets and we can query for them and dereference them in typesafe manner, with autocompletion, etc.

 

I have hit a roadblock when I tried to use it and realized that I can not use class-literals in Kotlin...

 

Please let me know if there is some other more idiomatic way of achieving similar objective.

Evgeny Gerashchenko JetBrains 114 posts since
Dec 8, 2009
Currently Being Moderated
Feb 19, 2013 1:01 PM in response to: Dimitar Dimitrov
Re: Class Literals

There is javaClass<T>() function which substitutes class literal expression. Here is usage for your example:

e.facet(javaClass<SomeData>())

 

 

P. S. Yes, there are named arguments in Kotlin, see corresponding docs article.

Evgeny Gerashchenko JetBrains 114 posts since
Dec 8, 2009
Currently Being Moderated
Feb 19, 2013 1:58 PM in response to: Dimitar Dimitrov
Re: Class Literals

No, they are not reified. Reified generics can be implemented for JVM only with big performance overhead, and we decided to cancel this feature.

 

javaClass() is a special function which is kind of reified, but not exactly. When it is called with concrete class as type argument, it is compiled to analog of java's ".class" expression. But you can't call it with another type parameter as type argument (e.g., javaClass<T>()). Just now it will compile, but it's incorrect, and will provoke compilation error later.

More Like This

  • Retrieving data ...