groovy-lecture/klassen&methoden.md

363 lines
7.4 KiB
Markdown
Raw Normal View History

2024-05-22 17:58:29 +02:00
# Klassen
### Definition einer Klasse
2024-05-19 17:34:24 +02:00
2024-05-19 17:39:34 +02:00
2024-05-19 17:34:24 +02:00
Klassen in Groovy werden ähnlich wie in Java definiert, jedoch mit einigen
syntaktischen Erleichterungen
Beispiel
```
class Person {
String name
int age
}
```
2024-05-22 17:58:29 +02:00
### Eigenschaften
2024-05-19 17:39:34 +02:00
Eigenschaften können direkt als Felder definiert werden. Groovy
generiert automatisch Getter- und Setter-Methoden (wie in Ruby)
2024-05-19 17:34:24 +02:00
Beispiel
```
Person person = new Person()
person.name = "John"
person.age = 30
person.age = 30
println person.name
//John
```
2024-05-19 17:39:34 +02:00
2024-05-19 17:34:24 +02:00
Getter und Setter können aber auch manuell überschrieben werden
Beispiel
```
class Fruits {
private String fruitName
private String fruitColor
def setFruitName(String name) {
fruitName = name
}
def getFruitName() {
return "The fruitname is $fruitName"
}
def setFruitColor(String color) {
fruitColor = color
}
def getFruitColor(){
return "The color is $fruitColor"
}
static void(args) {
//Instanz erstellen
Fruits apple = new Fruits()
apple.setFruitName("apple")
apple.setFruitColor("red")
}
}
```
2024-05-22 17:58:29 +02:00
### Konstruktoren
2024-05-19 17:39:34 +02:00
Groovy fügt automatisch einen Standardkonstruktor hinzu. Man kann auch
benutzerdefinierte Konstruktoren definieren.
2024-05-19 17:34:24 +02:00
```
class Person {
String name
int age
Person(String name, int age) {
this.name = name
this.age = age
}
}
```
2024-05-22 17:58:29 +02:00
### Standardkonstruktor mit Map
2024-05-19 17:39:34 +02:00
Groovy bietet eine spezielle Initialisierungsform mit einer Map an
2024-05-19 17:34:24 +02:00
```
Person person = new Person(name: 'John', age: 30)
```
2024-05-22 17:58:29 +02:00
2024-05-19 17:34:24 +02:00
2024-05-22 17:58:29 +02:00
# Methoden
2024-05-19 17:34:24 +02:00
2024-05-22 17:58:29 +02:00
### Definition einer Methode
2024-05-19 17:39:34 +02:00
2024-05-19 17:34:24 +02:00
Methoden werden ähnlich wie in Java definiert, können aber optional einen Rückgabetyp
haben
```
class Calculator {
int add(int a, int b) {
return a + b
}
}
```
2024-05-19 17:39:34 +02:00
In Groovy können Methoden direkt ohne Klasse und main-Methode definiert und aufgerufen
werden.
2024-05-19 17:34:24 +02:00
Beispiel 1
```
def printHello() {
println "Hello..."
}
printHello()
def sum(int a, int b) {
println "Sum is "+(a+b)
}
sum(5,2)
//Hello...
// 7
```
2024-05-22 17:58:29 +02:00
### Instanzmethoden
2024-05-19 17:39:34 +02:00
2024-05-19 17:34:24 +02:00
Methoden können Instanzmethoden sein und auf Instanzvariablen zugreifen.
```
class Method {
static void main(args) {
Method myFunc = new Method()
myFunc.myMethod()
}
def myMethod() {
println("I am inside my method")
}
}
```
2024-05-22 17:58:29 +02:00
### Statische Methoden
2024-05-19 17:34:24 +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
}
}
```
2024-05-22 17:58:29 +02:00
### Dynamische Methoden
2024-05-19 17:39:34 +02:00
2024-05-19 17:34:24 +02:00
Groovy erlaubt es, Methoden zur Laufzeit hinzuzufügen.
2024-05-19 17:39:34 +02:00
In diesem Beispiel wird die Methode sayHello zur Klasse DynamicExample hinzugefügt, nachdem
die Klasse bereits definiert wurde
2024-05-19 17:34:24 +02:00
Beispiel
```
class DynamicExample {}
// Hinzufügen einer Methode zur Laufzeit
DynamicExample.metaClass.sayHello = { -> println "Hello, World!" }
def example = new DynamicExample()
example.sayHello()
```
2024-05-22 17:58:29 +02:00
### Expando
Expando ist eine spezielle Klassen in Groovy, die ermöglicht, Objekten zur Laufzeit dynamisch Methoden und Eigenschaften hinzuzufügen. Dadurch ist die vorherige Deklaration der Felder in der Klasse nicht nötig
2024-05-19 17:39:34 +02:00
2024-05-19 17:34:24 +02:00
Beispiel
```
// Erstellen eines Expando-Objekts
def expando = new Expando()
// Hinzufügen einer Eigenschaft 'name' und Zuweisung des Wertes "Groovy"
expando.name = "Groovy"
// Hinzufügen einer Methode 'sayHello', die eine Nachricht ausgibt, die die Eigenschaft 'name' verwendet
expando.sayHello = { -> println "Hello from $name" }
// Aufrufen der Methode 'sayHello', was die Nachricht "Hello from Groovy" ausgibt
expando.sayHello() // Ausgabe: Hello from Groovy
```
2024-05-22 17:58:29 +02:00
### Default-Parameter
2024-05-19 17:39:34 +02:00
2024-05-22 17:58:29 +02:00
Methodenparameter können Standdardwerte haben(wie in Ruby). Diese werden eingesetzt, falls beim Aufruf keine Parameter gesetzt werden.
2024-05-19 17:34:24 +02:00
Beispiel 1
```
class Greeter {
void greet(String name = "World") {
println "Hello, $name!"
}
}
```
Ruft man die Methode ohne Parameter auf, werden die Default-Paramter eingesetzt
2024-05-19 17:39:34 +02:00
2024-05-19 17:34:24 +02:00
Beispiel 2
```
def sum(int a=10, int b=3) {
println "Sum is "+(a+b)
}
sum()
```
2024-05-22 17:58:29 +02:00
### Closures
2024-05-19 17:39:34 +02:00
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.
2024-05-22 17:58:29 +02:00
Closures enthalten Parameter, den Pfeil -> und den auszuführenden Code. Parameter sind
optional und werden, sofern abgegeben, durch Kommas getrennt.
2024-05-19 17:34:24 +02:00
1. Parameter
```
2024-05-22 17:58:29 +02:00
//closure takes one parameter - name - and prints it when invoked
2024-05-19 17:34:24 +02:00
def greet = { String name -> println "Hello, $name!" }
greet.call("John")
```
2. Referenzierung von Variablen und Rückgabewerte
2024-05-22 17:58:29 +02:00
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-05-19 17:34:24 +02:00
```
def createCounter() {
2024-05-22 17:58:29 +02:00
def count = 0 //lokale var
2024-05-19 17:34:24 +02:00
return { ->
count += 1
return count
}
}
2024-05-22 17:58:29 +02:00
//Ergebnis bzw. closure wird counter zugewiesen
def counter = createCounter()
//counter hat zugriff auf count *innerhalb des Kontexts*
//in dem sie erstellt wurde
2024-05-19 17:34:24 +02:00
println(counter()) // Ausgabe: 1
println(counter()) // Ausgabe: 2
```
3. Übergabe als Parameter
```
def performOperation(int x, Closure operation) {
return operation(x)
}
def closure = { y -> y * 2 }
def result = performOperation(5, closure)
println(result) // Ausgabe: 10
```
2024-05-22 17:58:29 +02:00
### Wie ruft man eine Closure auf
Eine Closure kann sowohl als eine reguläre Methode als auch mit call aufrufen werden
```
// 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!
```
2024-05-19 17:34:24 +02:00
Methoden können auch auf Maps und Listen angewendet werden, besonders nützlich mit Closures.
2024-05-22 17:58:29 +02:00
2024-05-19 17:34:24 +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]
```
2024-05-22 17:58:29 +02:00
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
2024-05-19 17:39:34 +02:00
2024-05-19 17:34:24 +02:00
Durch das Rückgeben von this kann man Methodenaufrufe verketten.
2024-05-19 17:39:34 +02:00
2024-05-19 17:34:24 +02:00
Beispiel
```
class FluentPerson {
String name
int age
FluentPerson setName(String name) {
this.name = name
return this
}
FluentPerson setAge(int age) {
this.age = age
return this
}
}
def person = new FluentPerson().setName("John").setAge(30)
```
2024-05-19 17:39:34 +02:00
2024-05-22 17:58:29 +02:00
### Mixin(Misching)
2024-05-19 17:39:34 +02:00
Man kann Funktionalität zu Klassen hinzufügen, ohne Vererbung zu verwenden, indem man
Mixins verwendet.
2024-05-19 17:34:24 +02:00
Beispiel
```
class ExtraMethods {
String shout(String str) {
return str.toUpperCase()
}
}
@Mixin(ExtraMethods)
class MyClass {}
def myObject = new MyClass()
println myObject.shout("hello")
```