문제

This may be a duplicate but "as" is an INCREDABLY hard keyword to google, even S.O. ignores "as" as part of query.

So I'm wondering how to implement a class that supports "as" reflexively. For an example class:

class X {
    private val
    public X(def v) {
        val=v
    }
    public asType(Class c) {
        if (c == Integer.class)
            return val as Integer
        if(c == String.class)
            return val as String
    }
}

This allows something like:

new X(3) as String

to work, but doesn't help with:

3 as X

I probably have to attach/modify the "asType" on String and Integer somehow, but I feel any changes like this should be confined to the "X" class... Can the X class either implement a method like:

X fromObject(object)

or somehow modify the String/Integer class from within X. This seems tough since it won't execute any code in X until X is actually used... what if my first usage of X is "3 as X", will X get a chance to override Integer's asType before Groovy tries to call is?

도움이 되었습니까?

해결책

As you say, it's not going to be easy to change the asType method for Integer to accept X as a new type of transformation (especially without destroying the existing functionality).

The best I can think of is to do:

Integer.metaClass.toX = { -> new X( delegate ) }

And then you can call:

3.toX()

I can't think how 3 as X could be done -- as you say, the other way; new X('3') as Integer is relatively easy.


Actually, you can do this:

// Get a handle on the old `asType` method for Integer
def oldAsType = Integer.metaClass.getMetaMethod( "asType", [Class] as Class[] )

// Then write our own
Integer.metaClass.asType = { Class c ->
  if( c == X ) {
    new X( delegate )
  }
  else {
    // if it's not an X, call the original
    oldAsType.invoke( delegate, c )
  }
}

3 as X

다른 팁

This keeps the functionality out of the Integer type, and minimizes scope of the effect (which is good or bad depending on what you're looking for).

This category will apply asType from the Integer side.

class IntegerCategory {
    static Object asType(Integer inty, Class c) {
        if(c == X) return new X(inty)
        else return inty.asType(c)
    }
}

use (IntegerCategory) { 
    (3 as X) instanceof X
}
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top