groovy-lecture/skript/methoden.md

270 lines
6.3 KiB
Markdown
Raw Normal View History

2024-05-30 15:29:03 +02:00
# Methoden
### Definition einer Methode
Methoden werden ähnlich wie in Java definiert, können aber optional einen Rückgabetyp
haben
2024-06-08 01:30:12 +02:00
```Groovy
class Calculator {
int add(int a, int b) {
return a + b
}
2024-05-30 15:29:03 +02:00
}
```
In Groovy können Methoden direkt ohne Klasse und main-Methode definiert und aufgerufen
werden.
Beispiel 1
2024-06-08 01:30:12 +02:00
```Groovy
def printHello() {
println "Hello..."
2024-05-30 15:29:03 +02:00
}
printHello()
def sum(int a, int b) {
println "Sum is "+(a+b)
}
sum(5,2)
//Hello...
// 7
```
### Instanzmethoden
Methoden können Instanzmethoden sein und auf Instanzvariablen zugreifen, indem man $-Zeichen und optional eckige Klammern nutzt.
2024-05-30 15:29:03 +02:00
2024-06-08 01:30:12 +02:00
```Groovy
2024-05-30 15:29:03 +02:00
class Person {
String name
int age
// Instanzmethode, um die Person vorzustellen
def introduce() {
println("Hello, my name is $name and I am ${age} years old.")
2024-05-30 15:29:03 +02:00
}
}
Person person = new Person(name: 'Alice', age: 30)
person.introduce()
// Hello, my name is Alice and I am 30 years old.
```
### Statische Methoden
2024-06-08 01:30:12 +02:00
```Groovy
2024-05-30 15:29:03 +02:00
class MathUtils {
// Definition einer statischen Methode
static int add(int a, int b) {
return a + b
}
static void main(String[] args) {
// Aufruf der statischen Methode ohne Instanz der Klasse
int result = MathUtils.add(5, 10)
println("Sum is $result") // Ausgabe: Sum is 15
}
}
```
### Dynamische Methoden
Groovy erlaubt es, Methoden zur Laufzeit hinzuzufügen.
In diesem Beispiel wird die Methode sayHello zur Klasse DynamicExample hinzugefügt, nachdem
die Klasse bereits definiert wurde
Beispiel
Groovy ermöglicht es, Methoden zur Laufzeit hinzuzufügen, was eine hohe Flexibilität bei der Gestaltung
von Klassen und deren Verhalten bietet. Diese Fähigkeit ist Teil der dynamischen Natur von Groovy und
wird durch die metaClass-Eigenschaft ermöglicht
2024-06-08 01:30:12 +02:00
```Groovy
2024-05-30 15:29:03 +02:00
class DynamicExample {}
// Hinzufügen einer Methode(=closure) zur Laufzeit
DynamicExample.metaClass.sayHello = { -> println "Hello, World!" }
def example = new DynamicExample()
example.sayHello()
```
### Default-Parameter
Methodenparameter können Standdardwerte haben (wie in Ruby). Diese werden eingesetzt, falls beim Aufruf keine Parameter
gesetzt werden.
Beispiel 1
2024-06-08 01:30:12 +02:00
```Groovy
2024-05-30 15:29:03 +02:00
class Greeter {
void greet(String name = "World") {
println "Hello, $name!"
}
}
```
Ruft man die Methode ohne Parameter auf, werden die Default-Paramter eingesetzt
Beispiel 2
2024-06-08 01:30:12 +02:00
```Groovy
2024-05-30 15:29:03 +02:00
def sum(int a=10, int b=3) {
println "Sum is "+(a+b)
}
sum()
// Sum is 13
```
### Closures
Closures können auf Variablen aus ihrem umgebenden Gültigkeitsbereich zugreifen und diese
„einfangen“. Dadurch können sie auf Werte zugreifen, die zum Zeitpunkt ihrer Erstellung
existierten.
Closures enthalten Parameter, den Pfeil -> und den auszuführenden Code. Parameter sind
optional und werden, sofern angegeben, durch Kommas getrennt.
1. Parameter
2024-06-08 01:30:12 +02:00
```Groovy
2024-05-30 15:29:03 +02:00
//closure takes one parameter - name - and prints it when invoked
def greet = { String name -> println "Hello, $name!" }
greet.call("John")
```
2. Referenzierung von Variablen und Rückgabewerte
Dieses Beispiel zeigt, wie Closures auf Variablen im auf Variablen im umgebenden Kontext
zugreifen und diese beibehalten können. Somit wird es Closures ermöglicht, Zustände
zwischen verschiedenen Aufrufen beizubehalten.
2024-06-08 01:30:12 +02:00
```Groovy
2024-05-30 15:29:03 +02:00
def createCounter() {
def count = 0 //lokale var
return { ->
count += 1
return count
}
}
//Ergebnis bzw. closure wird counter zugewiesen
def counter = createCounter()
//counter hat zugriff auf count *innerhalb des Kontexts*
//in dem sie erstellt wurde
println(counter()) // Ausgabe: 1
println(counter()) // Ausgabe: 2
```
3. Übergabe als Parameter
2024-06-08 01:30:12 +02:00
```Groovy
2024-05-30 15:29:03 +02:00
def performOperation(int x, Closure operation) {
return operation(x)
}
def closure = { y -> y * 2 }
def result = performOperation(5, closure)
println(result) // Ausgabe: 10
```
### Wie ruft man eine Closure auf
Eine Closure kann sowohl als eine reguläre Methode als auch mit call aufrufen werden
2024-06-08 01:30:12 +02:00
```Groovy
2024-05-30 15:29:03 +02:00
// Closure-Definition
def greet = { name ->
return "Hello, ${name}!"
}
// Aufruf der Closure als reguläre Methode
println(greet("Alice")) // Ausgabe: Hello, Alice!
// Aufruf der Closure mit call
println(greet.call("Bob")) // Ausgabe: Hello, Bob!
```
Methoden können auch auf Maps und Listen angewendet werden, besonders nützlich mit Closures.
2024-06-08 01:30:12 +02:00
```Groovy
2024-05-30 15:29:03 +02:00
def myMap = [ 'subject': 'groovy', 'topic': 'closures']
println myMap.each { it }
def myList = [1, 2, 3, 4, 5]
println myList.find { item -> item == 3 } // 3
println myList.findAll { item -> item > 3 } // [4, 5]
println myList.any { item -> item > 5 } // false
println myList.every { item -> item > 3 } // false
println myList.collect { item -> item * 2 } // [2, 4, 6, 8, 10]
```
Im Gegensatz zu einer regulären Groovy-Methode:
- Wir können eine Closure als Argument an eine Methode übergeben
- Wir können eine Closure einer Variablen zuweisen und später ausführen, entweder als Methode oder mit call.
- Groovy bestimmt den Rückgabewert der Closures zur Laufzeit.
- Wir können Closures innerhalb einer Closure deklarieren und aufrufen.
- Closures geben immer einen Wert zurück
### Methodenverkettung
Methodenverkettung ermöglicht,dass Methodenaufrufe direkt nacheinander aufeinanderfolgen können, indem das Objekt
selbst (normalerweise mit this) zurückgegeben wird.
Dies ermöglicht eine flüssige und verständliche Art, Methoden aufzurufen und zu kombinieren, insbesondere wenn diese
Methoden denselben oder ähnlichen Kontext haben. (wie in JS, )
Beispiel
2024-06-08 01:30:12 +02:00
```Groovy
2024-05-30 15:29:03 +02:00
class FluentPerson {
String name
int age
FluentPerson setName(String name) {
this.name = name
return this
}
FluentPerson setAge(int age) {
this.age = age
return this
}
}
// Erstellen einer neuen FluentPerson-Instanz und Methodenverkettung
def person = new FluentPerson()
.setName("Alice")
.setAge(30)
println "Name: ${person.name}, Age: ${person.age}" // Ausgabe: Name: Alice, Age: 30
```
### Mixin(Misching)
Man kann Funktionalität zu Klassen hinzufügen, ohne Vererbung zu verwenden, indem man
Mixins verwendet.
Beispiel
2024-06-08 01:30:12 +02:00
```Groovy
2024-05-30 15:29:03 +02:00
class ExtraMethods {
String shout(String str) {
return str.toUpperCase()
}
}
@Mixin(ExtraMethods)
class MyClass {}
def myObject = new MyClass()
println myObject.shout("hello")
```