| 

.NET C# Java Javascript Exception

Meta Objekt Protokoll

Dies ist das Archiv des ehemaligen Forums zum Thema Groovy, Grails, Griffon und Bean Scripting Framework, welches unter groovy-forum.de existierte. Die neue Adresse des Groovy-Forums ist: http://codekicker.de/fragen/themen/groovy.


[|Start] > [Groovy-Buch] > Objektorientierung > [{$pagename}]
[{TableOfContents}]
!!! Einführung in das Meta-Objekt-Protokoll
Mit der klassischen Objektorientierung lässt sich das Verhalten einer Klasse nur in folgenden Varianten ändern:
# direktes Ändern der Implementierung
# Ableiten der Klasse und Überschreiben der Methode
# Injizierung von Code – falls die fremde Klasse eine Injizierung vorgesehen hat
Leider gibt es Fälle, in denen keines der genannten Vorgehen möglich oder vorhanden ist.\\
Z.B. weil Du eine Klasse aus einer fremden Bibliothek verwendest, die am Anfang oder mitten in in einer längeren Vererbungshierachie steht und keine Möglichkeit zur Injizierung vorgesehen hat.
Das Meta-Objekt-Protokoll (MOP) adressiert dieses Problem, indem es die Semantik eines Programmes – auch zur Laufzeit – erweitern kann. Dazu bringt es die Eigenschaft mit, daß jedes Objekt über eine Metaklasse verfügt.\\
Diese lässt sich als eine übliche Klasse betrachten, deren Eigenschaften und Verhalten jedoch bei der attributierten Klasse verfügbar ist, so als würde nur eine einzige Klasse vorliegen. Dabei haben die Eigenschaften der Metaklasse Vorrang, sie ''überschreiben'' gewissermaßen das Verhalten der attributierten Klasse.
Darüber hinaus gelten für eine Klasse nicht nur die Methoden, Attribute usw. die deren Metaklasse mitbringt, sondern auch die von den Metaklasse aus der ererbten Hierarchie.
__Beispiel:__\\
Die Klasse {{{java.lang.String}}} verfügt über alle Methoden und Attribute
* ihrer eigenen Definition
* ihrer Metaklasse
* von {{{java.lang.Object}}}
* der Metaklasse von {{{java.lang.Object}}}
Der bekannteste Vertreter ist die Methode {{{println}}}, die in jeder Klasse verfügbar ist.
Diese wurde in der Metaklasse von {{java.lang.Object}} hinterlegt.
!!! Nutzungsmöglichkeiten
!! Abfragen aller Methoden
%%prettify
{{{
def obj = "Ein Text"
def metaClass = obj.metaClass
metaClass.methods.each {
println it.name
}
}}}
/%
!! Prüfung auf Methoden
%%prettify
{{{
def obj = "ein Text"
if (obj.metaClass.respondsTo(obj,"toUpperCase")) {
println obj.toUpperCase
}
// auch möglich: if(obj.toUpperCase) { ... }
}}}
/%
!! Prüfung auf Attribute
%%prettify
{{{
if (obj.metaClass.hasProperty("bytes")) {
println obj.bytes.encodeAsBase64()
}
}}}
/%
!! statische Methoden
%%prettify
{{{
Klasse.metaClass.static.neu = { ... }
}}}
/%
!! Konstruktoren
%%prettify
{{{
Klasse.metaClass.constructor = { String eingabe ->
...
}
}}}
/%
!! Nie mehr {{{MissingMethodException}}}
%%prettify
{{{
Klasse.metaClass.methodMissing = {
String name, def args ->
...
}
}}}
/%
!! Weitere Möglichkeiten
getProperty, setProperty, propertyMissing, invokeMethod
* Möglichkeit für Interzeptoren
* Ansatz der Aspektorientierten Programmierung
!! Dynamische Funktionen generierbar
Die bisherigen Beispiele zeigten nur auf, wie statische (namentlich fixierte) Funktionen geschaffen werden können. Aber es lassen sich auf dem gleichen Wege dynamische Funktionen erstellen, also Funktionen, die nicht explizit durch den Namen bekannt sind.\\
Hierzu muss die bereits zuvor erwähnte {{{Klasse.metaClass.methodMissing}}} implementiert werden.
__Beispiel__\\
Du willst auf jeder Liste die Möglichkeit haben, eine Art von Selektion durchzuführen. Dabei ist nur bekannt, daß es eine Menge von Operatoren gibt, die für Dich interessant sind (Gleichheit, größer als, kleiner als, wertemäßig zwischen zwei Werten usw.). Das konkrete Objekt, das in der Liste vorhanden ist, ist unbekannt.
In Deiner konkreten Implementierung von {{{java.util.List.metaClass.methodMissing}}} reagierst Du darauf, wenn eine Methode mit dem Präfix {{{findAllWhere}}} beginnt und mit einem der Operatoren endet. Die Parameter beziehen sich auf den Operator.\\
Alles zwischen Präfix und dem Operator wird als Attribut des Objektes aus der Liste angenommen.
Damit kannst Du jetzt bei jeder beliebigen Liste Deine dynamische Funktion aufrufen, wie hier bei einer Liste von Personen:
%%prettify
{{{
List<Person> personen
personen.findAllWhereVornameEquals("Marc")
personen.findAllWhereAlterBetween(28,38)
}}}
/%
Die Möglichkeit, dynamisch Funktionen zu generieren, ist ein sehr wichtiger Schritt in Richtung der [domänenspezifischen Sprachen|http://de.wikipedia.org//Dom%C3%A4nenspezifische_Programmiersprache] (engl.: domain specific language; DSL) und wird an mehreren Stellen in ''Groovy'' genutzt.
!!! Aufgaben
* noch ''schick'' machen
* ausformulieren [Marc Pompl|MarcPompl]

Diese Seite zeigt Informationen zu "Meta Objekt Protokoll" der ehemaligen Webseite groovy-forum.de, welche durch einen Serverunfall zerstört wurde. codekicker.de hat viele Konversationen über die beliebte Programmiersprache Groovy und zugehörige Frameworks wie das Grails-Framework retten können.

Hast Du eine Frage zum Thema Groovy, Grails oder allgemein Java? Viele ehemalige groovy-forum.de Mitglieder beantworten dir auf codekicker.de deine Frage! Stelle jetzt eine Frage!

Viele weitere Diskussionen zu Grails und Groovy befinden sich auf der Threadübersicht des alten groovy-forum.de.