2010-08-23 16 views
7

Me gustaría volver a implementar un método de una clase Java. Por ejemplo, para "hi".length() para devolver 4. (¿Cómo puedo hacer eso?¿Puedo redefinir String # length?

Sé usar SomeClass.metaClass Puedo obtener una referencia a un método existente y definir un método nuevo (o invalidado), pero parece que no puedo hacer eso con los métodos Java existentes.

+0

Eso sería un comportamiento incorrecto. Es posible que pueda usar un método 'pad()' que extendería su cadena a una longitud máxima dada. Entonces podrías llamar longitud a esa cadena. – Nate

+0

¿Qué te gusta lograr con eso? Romperías un montón de código de esta manera. –

+0

¿Por qué? ¿Cuántas cosas puedes romper haciendo esto? Puedo hacer 2 + 2 = 5, pero puede que realmente no sea la mejor solución. ¿Quizás simplemente quiera ajustar el valor devuelto en algunas situaciones especiales? – mickeyf

Respuesta

2

Parece que podría ser posible por abusing Cadena metaClass. Pero el intento que he hecho hasta ahora en la consola maravilloso no condujo al resultado esperado:

def oldLength = String.metaClass.length 
String.metaClass.length = { -> 
    return oldLength+10; 
} 

println "hi".length() 

da salida a la triste 2

Creo que se podría echar un vistazo a Proxy MetaClass o Delegating metaClass.

+0

Creo que el problema está relacionado con este problema: http://jira.codehaus.org/browse/GROOVY-3493 –

+1

Parece que sí, esto funciona: String.metaClass.invokeMethod = {String methodName, args -> println (" hola ") } " hola ".length() // imprime" hola " – IttayD

+0

¿Por qué se ha aceptado esta respuesta cuando, por propia admisión del autor, no funciona? –

1

Si lo redefinió, solo funcionaría en el código de Groovy. Groovy no puede cambiar la forma en que se ejecuta el código Java.

En Groovy, "hi".length() es más o menos equivalente a este Java:

stringMetaClass.invokeMethod("hi","length"); 

Debido maravilloso en realidad no llamar directamente longitud, trucos MetaClass trabajan en el código Groovy. Pero Java no sabe acerca de MetaClasses, por lo que no hay forma de que esto funcione.

+0

sí, por favor, muéstrame cómo hacerlo solo para groovy – IttayD

4

Usando Groovy, puede reemplazar cualquier método (incluso los de las clases finales) con su propia implementación. El reemplazo de métodos en Groovy utiliza el protocolo metaobjeto, no la herencia.

Aquí está el ejemplo que ha solicitado, es decir, cómo hacer String.length() siempre devuelven 4

// Redefine the method 
String.metaClass.invokeMethod = { name, args -> 

    def metaMethod = delegate.metaClass.getMetaMethod(name, args) 
    def result = metaMethod.invoke(delegate, args) 

    name == 'length' ? 4 : result 
} 

// Test it 
assert "i_do_not_have_4_chars".length() == 4 
+0

nota para los demás que pueden preguntarse por qué esto no fue aceptado como una respuesta: se envió después de comentar que esta es la solución en la respuesta anterior – IttayD

+0

Puede dejar de aceptar la otra respuesta y aceptar esta si lo considera mejor. Simplemente haga clic en la marca de verificación verde para no aceptarlo. –