La metaprogramació és una tècnica avançada que permet als programes escriure o modificar altres programes (o a si mateixos) en temps d'execució. Groovy, amb la seva naturalesa dinàmica, ofereix potents capacitats de metaprogramació que permeten als desenvolupadors crear codi més flexible i adaptable.
Conceptes Clau de la Metaprogramació en Groovy
- MetaClass: Cada classe en Groovy té una MetaClass associada que permet modificar el comportament de les instàncies de la classe.
- ExpandoMetaClass: Una extensió de MetaClass que permet afegir mètodes i propietats a les classes de manera dinàmica.
- Method Missing: Permet interceptar les crides a mètodes que no existeixen.
- Property Missing: Permet interceptar l'accés a propietats que no existeixen.
- Categories: Permeten afegir mètodes a les classes de manera temporal dins d'un bloc de codi.
MetaClass
La MetaClass és el mecanisme central de la metaprogramació en Groovy. Permet modificar el comportament de les classes i les seves instàncies.
Exemple: Afegir un Mètode a una Classe
class Persona {
String nom
}
Persona.metaClass.saluda = { -> "Hola, sóc $nom" }
def persona = new Persona(nom: 'Joan')
println(persona.saluda()) // Sortida: Hola, sóc JoanExplicació:
Persona.metaClass.saluda = { -> "Hola, sóc $nom" }: Afegim un mètodesaludaa la classePersonautilitzant la seva MetaClass.def persona = new Persona(nom: 'Joan'): Creem una instància dePersona.println(persona.saluda()): Cridem el nou mètodesaludaque hem afegit dinàmicament.
ExpandoMetaClass
L'ExpandoMetaClass permet afegir mètodes i propietats a les classes de manera dinàmica i és especialment útil per a la metaprogramació.
Exemple: Afegir un Mètode Estàtic
ExpandoMetaClass.enableGlobally()
String.metaClass.static.saluda = { -> "Hola des de la classe String!" }
println(String.saluda()) // Sortida: Hola des de la classe String!Explicació:
ExpandoMetaClass.enableGlobally(): Habilitem l'ExpandoMetaClass globalment.String.metaClass.static.saluda = { -> "Hola des de la classe String!" }: Afegim un mètode estàticsaludaa la classeString.println(String.saluda()): Cridem el mètode estàticsaluda.
Method Missing
El mètode methodMissing permet interceptar les crides a mètodes que no existeixen en una classe.
Exemple: Implementar methodMissing
class DynamicMethods {
def methodMissing(String name, args) {
return "El mètode $name no existeix, però ha estat interceptat!"
}
}
def obj = new DynamicMethods()
println(obj.unMetodeInexistent()) // Sortida: El mètode unMetodeInexistent no existeix, però ha estat interceptat!Explicació:
def methodMissing(String name, args): Definim el mètodemethodMissingque intercepta les crides a mètodes inexistents.println(obj.unMetodeInexistent()): Cridem un mètode que no existeix, però és interceptat permethodMissing.
Property Missing
El mètode propertyMissing permet interceptar l'accés a propietats que no existeixen en una classe.
Exemple: Implementar propertyMissing
class DynamicProperties {
def propertyMissing(String name) {
return "La propietat $name no existeix, però ha estat interceptada!"
}
}
def obj = new DynamicProperties()
println(obj.unaPropietatInexistent) // Sortida: La propietat unaPropietatInexistent no existeix, però ha estat interceptada!Explicació:
def propertyMissing(String name): Definim el mètodepropertyMissingque intercepta l'accés a propietats inexistents.println(obj.unaPropietatInexistent): Accedim a una propietat que no existeix, però és interceptada perpropertyMissing.
Categories
Les categories permeten afegir mètodes a les classes de manera temporal dins d'un bloc de codi.
Exemple: Utilitzar Categories
class StringCategory {
static String reverseString(String self) {
return self.reverse()
}
}
use(StringCategory) {
println "Hola".reverseString() // Sortida: aloH
}Explicació:
class StringCategory: Definim una classe de categoria amb un mètodereverseString.use(StringCategory) { ... }: Utilitzem la categoriaStringCategorydins del bloc de codi.println "Hola".reverseString(): Cridem el mètodereverseStringafegit temporalment a la classeString.
Exercicis Pràctics
Exercici 1: Afegir un Mètode Dinàmic
Afegiu un mètode dinàmic diHola a la classe Persona que imprimeixi "Hola, sóc [nom]".
Solució:
class Persona {
String nom
}
Persona.metaClass.diHola = { -> "Hola, sóc $nom" }
def persona = new Persona(nom: 'Maria')
println(persona.diHola()) // Sortida: Hola, sóc MariaExercici 2: Interceptar Mètodes Inexistents
Creeu una classe DynamicClass que intercepti les crides a mètodes inexistents i retorni un missatge personalitzat.
Solució:
class DynamicClass {
def methodMissing(String name, args) {
return "El mètode $name no existeix, però ha estat interceptat!"
}
}
def obj = new DynamicClass()
println(obj.metodeInexistent()) // Sortida: El mètode metodeInexistent no existeix, però ha estat interceptat!Resum
En aquesta secció, hem explorat les capacitats de metaprogramació de Groovy, incloent MetaClass, ExpandoMetaClass, methodMissing, propertyMissing i categories. Aquestes eines permeten als desenvolupadors crear codi més flexible i adaptable, i són especialment útils per a la creació de DSLs i altres aplicacions avançades.
Curs de Programació Groovy
Mòdul 1: Introducció a Groovy
Mòdul 2: Sintaxi i Característiques del Llenguatge Groovy
Mòdul 3: Programació Orientada a Objectes en Groovy
Mòdul 4: Característiques Avançades de Groovy
Mòdul 5: Groovy en la Pràctica
- Entrada/Sortida de Fitxers
- Treballant amb XML i JSON
- Accés a Bases de Dades
- Desenvolupament Web amb Groovy
Mòdul 6: Proves i Depuració
Mòdul 7: Ecosistema i Eines de Groovy
- Eina de Construcció Gradle
- Framework de Proves Spock
- Framework Grails
- Altres Llibreries i Eines de Groovy
Mòdul 8: Millors Pràctiques i Temes Avançats
- Estil de Codi i Convencions
- Optimització del Rendiment
- Consideracions de Seguretat
- Concurrència en Groovy
