Any way in Groovy/Java to identify the subclass calling a static method?

点点圈 提交于 2019-12-24 06:11:34

问题


Groovy is so powerful I wonder whether there's an easy way to do this.

The scenario:

I have an abstract class, AbstractSequence. Then I have two (more in reality) subclasses, called say CasedSequence and LowerCaseSequence. Each of these concrete classes has to have an "identity map", i.e. like a Set but where it is possible to extract an element based on functional equality (overriding of equals and hashCode).

So we have:

class CasedSequence extends AbstractSequence {
    static Map identityMap = [:]
...

class LowerCaseSequence extends AbstractSequence {
    static Map identityMap = [:]

In fact, for reasons that would take too long to explain, manipulation of these identity maps in the respective classes also uses lots of static methods, all similar/identical from one subclass to the other. So I wondered how one might refactor to put the identity maps in the abstract base class (and then migrate a lot of the repetitive static methods there).

This led me to this:

abstract class AbstractSequence {

    static Map getIdentityMap( Class clazz ) {
        if( ! ( clazz in identityMaps )) 
            identityMaps[ clazz ] = [ : ]
        identityMaps[ clazz ]
    }
    static Map identityMaps = [:]

and then in the concrete classes, each time you want to use the identity map you have to do this:

class CasedSequence extends AbstractSequence {
    def someMethod( CasedSequence seq1 ){
        CasedSequence seq2 = getIdentityMap( CasedSequence )[ seq1 ] 
...

Again, it's too complicated to explain why you need to retrieve things this way... but I'm just wondering whether there's a way (an elegant Groovy way?) in AbstractSequence.getIdentityMap() to identify the class of the subclass calling getIdentityMap(), rather than having to pass this class as a parameter?

PS I'd rather not use Thread.stackTrace: it's cumbersome and won't deliver the actual class object, only the class name, and also stack traces in Groovy are wild. I'm thinking more in terms of Groovy reflection, Groovy metaclasses...


回答1:


Would be interested in hearing from any Groovy gurus about this.

In the mean time I have used a bit of Groovy magic for a workaround, taking advantage of the fact that the Groovy GDK adds some methods to the class class, one being newInstance() - pretty useful. This "makes or gets" a sequence object depending on whether or not the sought sequence is already in the identity map.

    static makeOrGet( String string, Class clazz ) {
        def dummySeq = clazz.newInstance( DUMMY_STRING )
        // NB the constructor identifies the string DUMMY_STRING to prevent this new object being 
        // properly "registered" (i.e. put in the identity map), which would be wrong because 
        // the dummy seq is just to find out whether the sequence with "string" is actually 
        // present in the map

        def seq
        // disguise the dummy sequence to flush out an existing sequence with String "string"
        dummySeq.string = string
        if( dummySeq in getIdentityMap( clazz ) )
            seq = getIdentityMap( clazz )[ dummySeq ]
        else
            // NB constructor puts the new "clazz" object in the identity map
            seq = clazz.newInstance( string )
        seq
    }

... so the above method can be called with various different classes as parameter 2 and then delivers an object of class clazz, either extracted from the identity map or constructed (and put in the map).



来源:https://stackoverflow.com/questions/57019972/any-way-in-groovy-java-to-identify-the-subclass-calling-a-static-method

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!