Skip to content

Commit

Permalink
Prepare lecture OOP
Browse files Browse the repository at this point in the history
  • Loading branch information
s-macke committed Oct 19, 2024
1 parent b0e6aeb commit 2be1fa6
Show file tree
Hide file tree
Showing 10 changed files with 289 additions and 32 deletions.
134 changes: 118 additions & 16 deletions docs/03-Go-Programming-OOP.slide
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ Go Programming - OOP
Concepts of Programming Languages
Tags: go, programming, master

Sebastian Macke, Stefan Langer
Sebastian Macke
Rosenheim Technical University
Sebastian.Macke@th-rosenheim.de
https://www.qaware.de
Expand Down Expand Up @@ -58,6 +58,7 @@ The "defer" statement lets us ensure that code runs before a function exits
* Exception Pro and Cons

- What do you think are the pros and cons of exceptions?
- Miro Board ...

: * Exception Pro and Cons

Expand Down Expand Up @@ -223,17 +224,105 @@ The variable *r* is in both cases similar to the Java *this*, which reference to
: Object Oriented Programming - Custom Types
: Go has no classes but types and functions

* Orthogonal: Encapsulation can be done with any type

.play ../src/oop/orthogonal/int.go


* Syntax level OOP

.play ../src/oop/Syntax_OOP/syntax_oop.go

* Syntax level OOP

Encapsulation of methods is basically is just a syntax element.

func (r *Rational) Multiply(y Rational) Rational {
....
}

is internally transformed into

func Multiply(r *Rational, y Rational) Rational {
....
}

A lot of languages do it this way.

* Syntax level OOP
: .play ../src/oop/oop_vs_procedural/bool.go

: - Go seems to convert the OOP style to procedural style. (OOP only on syntax level)


* Composition VS. Inheritance

Composition and inheritance are two ways to achieve code reuse and design modular systems

- Composition

class Engine {
....
}
class Car {
private Engine engine
}

- Inheritance

class Animal {
....
}

class Dog extends Animal {
}


* Composition VS. Inheritance?

Composition and inheritance are two ways to achieve code reuse and design modular systems

- Composition: A design principle where objects are formed by combining multiple smaller objects
- Inheritance: A mechanism where a new class derives properties and behaviors from an existing class


- Which Pros and Cons exist?
- [[https://miro.com/app/board/uXjVNekj0S8=/?share_link_id=355865373286]]
- Miro ...


: Pros composition
: - Flexibility
: - Loose Coupling
: - better encasulation
: - avoids fragile base class problems with partial implementations
: - easy to understand

: Cons composition
: - Could lead to more boilerplate
: - manage more objects - indirection complexity
: - no hierarchical relationship

: Pro Inheritance
: - natural hierarchies
: - less boilerplate
: - polymorphism

: Cons inheritance
: - tight coupling
: - Fragile base class
: - reduced flexibility
: - inappropriate abstractions, force relationships that don't naturally fit
: - single inheritance restriction
: - More memory, harder to compile


* The issue with inheritance

- https://www.youtube.com/watch?v=Ng8m5VXsn8Q&t=414s
- Runner and RunCounter

* Embedding
- Go does not support inheritance: Go supports embedding of other structs.
- Go does of course support composition.
- But Go does not support inheritance: Go supports embedding of other structs.
.code ../src/oop/embedding0/embed.go /Point/,8

.code ../src/oop/embedding0/embed.go /ColorPoint/,16
Expand All @@ -242,15 +331,18 @@ The variable *r* is in both cases similar to the Java *this*, which reference to

- Access to embedded field is identical to a normal field inside a struct
- Syntactically it is similar to inheritance in Java
- In Java this can be done with delegation.
- Overriding of methods is kind of supported, overloading is not!

: Overloading is generally not possible in Go

* Delegation of Functions in Go

- Overriding of methods is kind of supported, overloading is not!
comparison of behavior in Java and Go at
- ../src/oop/delegation/delegation.go
- ../src/oop/delegation/delegation.java
- ../src/oop/delegation2/delegation.go
- ../src/oop/delegation2/delegation.java

.play ../src/oop/delegation/delegation.go /type A/,

: prints "a.bar"
: real delegation should print "b.bar", because delegation means
Expand Down Expand Up @@ -280,15 +372,15 @@ In Go:
- Java interfaces are satisfied explicitly

class Door implements Switch {
public void Open() {}
public void Close() {}
public void Open() { ... }
public void Close() { ... }
}

- Go interfaces are satisfied implicitly

type Door struct {}
func (d *Door) Open() {}
func (d *Door) Close() {}
func (d *Door) Open() { ... }
func (d *Door) Close() { ... }

Door implicitly satisfies the interface OpenCloser

Expand All @@ -309,21 +401,30 @@ The print functions in the *fmt* package support the following interface
// The object implements stringer
}

- Issue: The detection is done at runtime.

* Polymorphism III: The stringer interface

.play ../src/oop/stringer/stringer.go

* Interfaces and Polymorphism
.play ../src/oop/polymorphism/polymorphism.go /func main/,/END2 OMIT/

* Recap: Go does support a dynamic type

.play ../src/basics/dynamic/main.go /START OMIT/,/END OMIT/

* Example: Send Mail with Go: A minimal Interface
.code ../src/oop/mail/mail.go /Message/,/END OMIT/
- A example interface for a service-oriented component
- any is an alias for an empty interface{} and hence matches all types

type any = interface{}


* Example: A type implements an interface when providing the required methods
.code ../src/oop/mail/smtp/sender.go /type/,/END OMIT/
: * Example: Send Mail with Go: A minimal Interface
: .code ../src/oop/mail/mail.go /Message/,/END OMIT/
: - A example interface for a service-oriented component

: * Example: A type implements an interface when providing the required methods
: .code ../src/oop/mail/smtp/sender.go /type/,/END OMIT/

* Summary
- Go does support Encapsulation via an OOP style syntax
Expand All @@ -332,6 +433,7 @@ The print functions in the *fmt* package support the following interface
- Several interfaces can be put together to form an interface
- Interface embedding makes mocking easy
- Go supports polymorphism only via interfaces, not through classes
- https://youtu.be/Ng8m5VXsn8Q?t=414

: Inheritance can cause weak encapsulation, tight coupling and surprising bugs

Expand Down
5 changes: 1 addition & 4 deletions docs/exercises/Exercise2.2.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,7 @@ A Book Index is an inverted index which lists all pages a word occurs in a book.
Write a program which generates an inverted index out of an array of book pages.
Each Page contains an array of words.

- USe the "type" keyword to define custom types for Book, Page and Index.
- Make sure the Stringer() interface is implemented for Book and Index to make them printable
More details about the Stringer interface: https://tour.golang.org/methods/17
The stringer interface will be explained in more detail in the next lecture.
- Use the "type" keyword to define custom types for Book, Page and Index.
- Write a unit test which generates a book and calculates the index and prints it to Stdout

## After this Exercise
Expand Down
12 changes: 11 additions & 1 deletion docs/exercises/Exercise3.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

If you do not finish during the lecture period, please finish it as homework.

## Interfaces, Polymorphism and Embedding
## Excercise 3.1 Interfaces, Polymorphism and Embedding

The image shows a typical UML design with inheritance, aggregation and polymorph methods.

Expand All @@ -12,3 +12,13 @@ Implement this design as close as possible to the design in Go:

- The `Paint()` method should print the names and values of the fields to the console
- Allocate an array of polymorph objects and call Paint() in a loop

## Excercise 3.2 Stack (Containers)

Write a generic LIFO container (stack) for all types by using `any` as dynamic type by using the OOP approach.
The stack should have at least two methods:

- Push(object)
- Pop()

Use the array append function for Push and the slices feature for Pop
20 changes: 20 additions & 0 deletions src/oop/Syntax_OOP/syntax_oop.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package main

import "fmt"

type Bar struct{}

func (b *Bar) GetHello() string {
fmt.Println(b)
return "Hello"
}

type Foo struct {
B *Bar
}

func main() {
var f Foo
fmt.Println(f.B) // Output "nil"
fmt.Println(f.B.GetHello()) // Null Pointer error or "Hello"?
}
22 changes: 18 additions & 4 deletions src/oop/delegation/delegation.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,21 +2,35 @@ package main

import "fmt"

type A struct {}
type A struct{}

func (a A) Foo() {
fmt.Print("a.foo ")
a.Bar()
}

func (a A) Bar() {
fmt.Println("a.bar")
}

type B struct {
A
}

func (b B) Foo() {
fmt.Print("b.foo ")
b.Bar()
b.Bar() //b.A.Bar()
}

func (b B) Bar() {
fmt.Println("b.bar")
}

func main() {
b := B{}
b.Foo() // What happens?
a := A{}
a.Foo()
/*
b := B{}
b.Foo() // "a.bar" or "b.bar"?
*/
}
33 changes: 33 additions & 0 deletions src/oop/delegation/delegation.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
class A {
public void foo() {
System.out.print("a.foo ");
bar();
}

public void bar() {
System.out.println("a.bar");
}
}

class B extends A {
@Override
public void foo() {
System.out.print("b.foo ");
bar();
}
@Override
public void bar() {
System.out.println("b.bar");
}

}

public class Main {
public static void main(String[] args) {
// A a = new A();
// a.foo();

B b = new B();
b.foo(); // Will print "b.foo b.bar"
}
}
35 changes: 35 additions & 0 deletions src/oop/delegation2/delegation.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
package main

import "fmt"

type A struct{}

func (a A) Foo() {
fmt.Print("a.foo ")
a.Bar()
}

func (a A) Bar() {
fmt.Println("a.bar")
}

type B struct {
A
}

func (b B) Foo() {
fmt.Print("b.foo ")
b.A.Foo()
}

func (b B) Bar() {
fmt.Println("b.bar")
}

func main() {
a := A{}
a.Foo()

b := B{}
b.Foo() // "b.foo a.foo a.bar" or "b.foo a.foo b.bar"?
}
Loading

0 comments on commit 2be1fa6

Please sign in to comment.