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 Joan
Explicació:
Persona.metaClass.saluda = { -> "Hola, sóc $nom" }
: Afegim un mètodesaluda
a la classePersona
utilitzant la seva MetaClass.def persona = new Persona(nom: 'Joan')
: Creem una instància dePersona
.println(persona.saluda())
: Cridem el nou mètodesaluda
que 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àticsaluda
a 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ètodemethodMissing
que 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ètodepropertyMissing
que 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 categoriaStringCategory
dins del bloc de codi.println "Hola".reverseString()
: Cridem el mètodereverseString
afegit 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 Maria
Exercici 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