A Groovy programozási nyelv

Objektum-orientált programozás

Objektum Orientált Programozás (OOP)

Az objektum orientált szemlélet a Java-hoz nagyon hasonló. Például a nem primitív típusoknak (primitív: int, boolean stb.) létezik közös ősosztálya: az Object. Többszörös öröklődés nem megengedett, viszont egy osztály több interfészt is implementálhat. Minden úgy megy ahogy Java-ban megszokhattuk, talán az egyetlen kivétel: Groovyban az osztály field-jei, ha nem adunk meg explicit módon semmit, public-nak minősülnek. (Javaban az alapértelmezés az, hogy a field protected _és_ abból a csomagból mindenhonnan látható ahol az osztályt definiáltuk)
A továbbiakban néhány trükköt láthatunk arra, hogyan lehet interfészeket implementálni Groovy-ban másképp, closure-ökkel valamint map-pel.

Interfészek implementálása máshogyan, Groovyval

A Groovyban lehetőségünk nyílik interfészeket implementálni 2 különböző nem szokványos módon is.
Az első módszer, amikor egy closure-t (lásd: alprogramok fejezet) használunk ehhez. A következő példa mutatja, hogyan implementálhatunk egy interfészt, aminek csak 1 metódusa van (a kapcsos zárójelek közötti rész egy névtelen closure):

new Thread( {println "running"} as Runnable ).start()

Szintén használhatunk 1 closuret olyan interfészek implementálására is amiknek több metódusuk van, a következő példában láthatjuk, hogy ilyenkor minden metódushíváskor ugyanaz a closure fog végrehajtódni. Persze ilyenkor a closurenak paraméterlistájának meg kell egyeznie a metódus nevekkel, de a closure paramétereket - a Groovyban megszokott módon - "általánosnak" is definiálhatjuk objektumok egy tömbjével:

interface X { void f(); void g(int n); void h(String s, int n); } x = {Object[] args -> println "method called with $args"} as X x.f() x.g(1) x.h("hello",2)

Interfészek implementációját mappel is megadhatjuk. Ez a Groovyban használt általános módszer, többmetódusú interfészek implementálására. Példa:

impl = [ i: 10, hasNext: { impl.i > 0 }, next: { impl.i-- }, ] iter = impl as Iterator while ( iter.hasNext() ) println iter.next()

Csak azokat a metódusokat szükséges implementálni, amik aktuálisan meghívódnak, de ha valamit nem implementáltunk amit pedig meghívunk, egy NullPointerException fog kiváltódni:

interface X { void f(); void g(int n); void h(String s, int n); } x = [ f: {println "f called"} ] as X x.f() //x.g() // NPE here

A fenti as kulcsszó feltétele, hogy az implementálandó interfészre van referenciánk. Ellenkező esetben, ha az íráskor nem tudjuk a konkrét interfész nevét (pl: Class.forName-ből jön) az as helyett az asType-ot kell használnunk:

def loggerInterface = Class.forName( 'my.LoggerInterface' ) def logger = [ log : { Object[] params -> println "LOG: ${params[0]}"; if( params.length > 1 ) params[1].printStackTrace() }, close : { println "logger.close called" } ].asType( loggerInterface )