diff --git a/part_3/exercise_2/exercise_2.md b/part_3/exercise_2/exercise_2.md
new file mode 100644
index 0000000000000000000000000000000000000000..60e4a0b89654e499f64555e3830e97c57dd9e9ef
--- /dev/null
+++ b/part_3/exercise_2/exercise_2.md
@@ -0,0 +1,399 @@
+## a) Explain how inheritance and polymorphism manifest in the following cases. Pay special attention to the different catch branches.
+
+```java
+abstract class Problem extends Exception {}
+class WeirdProblem extends Problem {}
+class TrickyProblem extends Problem {}
+
+class Experiment {
+    void perform() throws WeirdProblem, TrickyProblem {
+        if (new java.util.Random().nextBoolean())
+            throw new WeirdProblem();
+        else
+            throw new TrickyProblem();
+    }
+}
+
+class Experiment2 {
+    void perform() throws Problem {
+        if (new java.util.Random().nextBoolean())
+            throw new WeirdProblem();
+        else
+            throw new TrickyProblem();
+    }
+}
+
+void main() {
+    var e1 = new Experiment();
+    var e2 = new Experiment2();
+
+    try {
+        e1.perform();
+        e2.perform();
+    }
+    catch (WeirdProblem w) {}
+    catch (TrickyProblem w) {}
+    catch (Problem w) {}
+}
+```
+
+### Answer:
+* **Inheritance** is expressed as the hierarchy below:
+```
+                                                                       
+                      ┌────────────────────────┐                       
+                      │                        │                       
+                      │        Exception       │                       
+                      │                        │                       
+                      └────────────▲───────────┘                       
+                                   │                                   
+                                   │                                   
+                                   │                                   
+                                   │                                   
+                      ┌────────────┴───────────┐                       
+                      │                        │                       
+                      │        Problem         │                       
+                      │                        │                       
+                      └────────────▲───────────┘                       
+                                   │                                   
+                                   │                                   
+                                   │                                   
+                                   │                                   
+                 ┌─────────────────┴───────────────────┐               
+                 │                                     │               
+     ┌───────────┴────────────┐          ┌─────────────┴──────────┐    
+     │                        │          │                        │    
+     │      WeirdProblem      │          │      TrickyProblem     │    
+     │                        │          │                        │    
+     └────────────────────────┘          └────────────────────────┘    
+                                                                       
+```
+
+* **Polymorphism** is recognized as the codes below:
+```java
+void main() {
+    var e1 = new Experiment();
+    var e2 = new Experiment2();
+
+    try {
+        e1.perform();
+        e2.perform();
+    }
+    catch (WeirdProblem w) {}
+    catch (TrickyProblem w) {}
+    catch (Problem w) {}
+}
+```
+In this code, **Polymorphism** is defined as the ability to reference an object (exception object in this case) through the type references of its superclass (`Problem`).
+
+If there is another class that extends `Problem`, and `Experiment2::perform()` throw an object of this class. For example:
+```java
+class AnotherProblem extends Problem {}
+
+class Experiment2 {
+    void perform() throws Problem {
+        if (new java.util.Random().nextBoolean())
+            throw new WeirdProblem();
+        else
+            if (new java.util.Random().nextBoolean())
+                throw new TrickyProblem();
+            else
+                throw new AnotherProblem();
+    }
+}
+```
+then in the
+```java
+void main() {
+    var e1 = new Experiment();
+    var e2 = new Experiment2();
+
+    try {
+        e1.perform();
+        e2.perform();
+    }
+    catch (WeirdProblem w) {}
+    catch (TrickyProblem w) {}
+    catch (Problem w) {
+        // We can catch the exception object of AnotherProblem here. 
+    }
+}
+```
+
+## b) Compare the following reuse methods (Printer1 and Printer2). What is each one about? How do they differ in their operating principles? How do the different methods support, for example, changing the decoration style?
+
+The previous Printer functionality needs to be extended in the Printer3 class so that instead of the previous decoration (decorate), the decoration adds the previously defined decoration to the beginning and end of the string, along with the characters --. What kind of implementation would this be? How would your solution differ if the number of -- characters used for decoration was not 2 per side but was read from a method described in the Decorator interface? What if it was in the Printer interface?
+
+```java
+interface Decorator {
+    String decorate(String input);
+}
+
+interface Printer {
+    void print(String s);
+    void run();
+}
+
+class Fancy implements Decorator {
+    @Override
+    public String decorate(String input) {
+        return "== " + input + " ==";
+    }
+}
+
+class Printer1 extends Fancy implements Printer {
+    @Override
+    public void print(String s) {
+        System.out.println(s);
+    }
+
+    @Override
+    public void run() {
+        print(decorate("test"));
+    }
+}
+
+class Printer2 implements Decorator, Printer {
+    private final Decorator decorator =
+            generateDecorator();
+
+    Decorator generateDecorator() {
+        return new Fancy();
+    }
+
+    @Override
+    public String decorate(String input) {
+        return decorator.decorate(input);
+    }
+
+    @Override
+    public void print(String s) {
+        System.out.println(s);
+    }
+
+    @Override
+    public void run() {
+        print(decorate("test"));
+    }
+}
+```
+
+The following code demonstrates test runs with the aforementioned classes Printer1 and Printer2, as well as the Printer3 class, which should be implemented:
+
+```java
+void main() {
+    new Printer1().run();
+    new Printer2().run();
+    new Printer3().run();
+}
+```
+
+Expected output: 
+```
+== main ==
+== main ==
+--== main ==--
+```
+
+### Answer:
+
+* **What is each one about?**
+
+    -> They have the same result when running (decorate the input string and print it), they inherit (implement) both `Printer` and `Decorator`.
+
+
+* **How do they differ in their operating principles?**
+
+    ->
+    - `Printer1` is using `Inheritance` (as it extends `Fancy`) to reuse the `decorate` method.
+    - `Printer2` is using `Composition` (delegate the decoration to an object of `Decorator`).
+
+
+* **How do the different methods support, for example, changing the decoration style?**
+
+    -> 
+    - `Printer1` depends on its superclass (`Fancy`), so in order to change, we may change its superclass (not recommended as it may change the behaviours of all subclasses) or override the methods of its superclass.
+For example: we may change the `Fancy::decorate()` code, or write a method `Printer1::decorate()` to override `Fancy::decorate()`.
+    - `Printer2` delegates to another object, so in order to change, just need to change the delegate.
+For example: we may change the `Printer2::generateDecorator()` to return another `Decorator` object.
+
+
+* **The previous Printer functionality needs to be extended in the Printer3 class so that instead of the previous decoration (decorate), the decoration adds the previously defined decoration to the beginning and end of the string, along with the characters --. What kind of implementation would this be?**
+
+    -> We use inheritance to reuse and extend the functionality. For example:
+
+```java
+class Printer3 extends Printer1 {
+    @Override
+    public String decorate(String input) {
+        return "--" + super.decorate(input) + "--";
+    }
+}
+```
+
+or
+
+```java
+class Printer3 extends Printer2 {
+    @Override
+    public String decorate(String input) {
+        return "--" + super.decorate(input) + "--";
+    }
+}
+```
+
+or
+
+```java
+class FancyDecorator implements Decorator {
+    private final Decorator decorator;
+    
+    public FancyDecorator() {
+        decorator = new Fancy();
+    }
+    
+    @Override
+    public String decorate(String input) {
+        return "--" + decorator.decorate(input) + "--";
+    }
+}
+class Printer3 extends Printer2 {
+    @Override
+    Decorator generateDecorator() {
+        return new FancyDecorator();
+    }
+}
+```
+
+* **How would your solution differ if the number of -- characters used for decoration was not 2 per side but was read from a method described in the Decorator interface?**
+
+  -> There will be small difference:
+```java
+interface Decorator {
+    String decorate(String input);
+    
+    default int getNumberOfCharacters() {
+        return 3;
+    }
+} 
+```
+
+and
+
+```java
+class Printer3 extends Printer1 {
+    @Override
+    public String decorate(String input) {
+        String addition = "-".repeat(this.getNumberOfCharacters());
+        
+        return addition + super.decorate(input) + addition;
+    }
+}
+```
+
+or
+
+```java
+class Printer3 extends Printer2 {
+    @Override
+    public String decorate(String input) {
+        String addition = "-".repeat(this.getNumberOfCharacters());
+        
+        return addition + super.decorate(input) + addition;
+    }
+}
+```
+
+or
+
+```java
+class FancyDecorator implements Decorator {
+    private final Decorator decorator;
+    
+    public FancyDecorator() {
+        decorator = new Fancy();
+    }
+    
+    @Override
+    public String decorate(String input) {
+        String addition = "-".repeat(this.getNumberOfCharacters());
+        
+        return addition + decorator.decorate(input) + addition;
+    }
+}
+class Printer3 extends Printer2 {
+    @Override
+    Decorator generateDecorator() {
+        return new FancyDecorator();
+    }
+}
+```
+
+* **What if it was in the Printer interface?**
+
+  -> 
+```java
+interface Printer {
+    void print(String s);
+    void run();
+    
+    default int getNumberOfCharacters() {
+        return 3;
+    }
+} 
+```
+
+and
+
+There will be no difference:
+```java
+class Printer3 extends Printer1 {
+    @Override
+    public String decorate(String input) {
+        String addition = "-".repeat(this.getNumberOfCharacters());
+        
+        return addition + super.decorate(input) + addition;
+    }
+}
+```
+
+or
+
+There will be no difference:
+```java
+class Printer3 extends Printer2 {
+    @Override
+    public String decorate(String input) {
+        String addition = "-".repeat(this.getNumberOfCharacters());
+        
+        return addition + super.decorate(input) + addition;
+    }
+}
+```
+
+but should be changed in this case:
+
+```java
+class FancyDecorator implements Decorator {
+    private final Decorator decorator;
+    private final int numberOfCharacters;
+    
+    public FancyDecorator(int numberOfCharacters) {
+        this.decorator = new Fancy();
+        this.numberOfCharacters = numberOfCharacters;
+    }
+    
+    @Override
+    public String decorate(String input) {
+        String addition = "-".repeat(this.numberOfCharacters);
+        
+        return addition + decorator.decorate(input) + addition;
+    }
+}
+class Printer3 extends Printer2 {
+    @Override
+    Decorator generateDecorator() {
+        return new FancyDecorator(this.getNumberOfCharacters());
+    }
+}
+```
\ No newline at end of file