Skip to content

Commit

Permalink
Add sealed classes and interfaces details (#160)
Browse files Browse the repository at this point in the history
  • Loading branch information
desislavaa authored Oct 23, 2024
1 parent dbdb42c commit 7f16cdd
Show file tree
Hide file tree
Showing 5 changed files with 100 additions and 40 deletions.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
140 changes: 100 additions & 40 deletions 03-oop-in-java-ii/lecture/slides.md
Original file line number Diff line number Diff line change
Expand Up @@ -282,6 +282,33 @@ public class EnumExample {

---

### Enum

```java
public class EnumExample {
public enum VehicleType {
CAR(4),
BICYCLE(2),
BOAT(0);

private final int numberOfWheels;

VehicleType(int numberOfWheels) {
this.numberOfWheels = numberOfWheels;
}

public int getNumberOfWheels() { return numberOfWheels; }
}

public static void main(String[] args) {
for (VehicleType vt : VehicleType.values()) {
System.out.printf("A %s has %d wheels \n", vt, vt.getNumberOfWheels());
}
}
}
```
---

class: center, middle

## Records
Expand Down Expand Up @@ -533,72 +560,104 @@ class: center, middle

---

### Sealed класове и интерфейси
### Sealed класове и интерфейси: какъв проблем решават?

```java
// sealed класовете декларират, кои класове могат да ги наследяват
public abstract sealed class Shape
permits Circle, Rectangle {...}
Имаме йерархия от класове, която има ограничен брой типове - подобно на enums.

// дефиниране на класове - наследници на sealed клас
public class Circle extends Shape {...} // OK
public class Rectangle extends Shape {...} // OK
public class Triangle extends Shape {...} // Compile error
Например:

// sealed класове като селектор на switch
// No need for default case if all permitted types are covered
double area = switch (shape) {
case Circle c -> Math.pow(c.radius(), 2) * Math.PI
case Rectangle r -> r.a() * r.b()
};
```
.center[![Hierarchy Example](images/03.6-sealed-hierarchy-1.png)]

---

### Sealed класове и интерфейси
### Sealed класове и интерфейси: какъв проблем решават?

На теория, стига да са `public` и да **не са** `final` или с `private`, всички класове могат да бъдат наследени:

- Като разрешаваме само на предварително дефинирано множество от класове да наследяват даден клас, може да разделим *достъпността* (*accessibility*) от *разширяемостта* (*extensibility*) на класовете
- С други думи, може да направим `sealed` клас достъпен за други пакети, и въпреки това да контролираме, кой може да го наследява
- Преди Java 17, за постигнем подобен ефект, имаше две опции:
- да направим класа package-private (което обаче ограничава достъпа до този клас)
- да направим класа `public`, но с `private` или package-private конструктори (това прави класа видим, но дава много ограничен контрол върху конкретните типове, които могат да го наследят)
.center[![Hierarchy Extensibility](images/03.6-sealed-hierarchy-2.png)]

---

### Sealed класове и интерфейси
### Sealed класове и интерфейси: какъв проблем решават?

- При `sealed` класовете и интерфейсите, съществува изчерпателен списък от наследниците, който е известен на компилатора, IDE-то и JVM-a, което позволява по-мощен анализ на кода
- например, `instanceof` и casts могат да проверяват цялата йерархия статично
#### Решение без sealed класове/интерфейси:

* дефинираме ги като `final`
* дефинираме ги като package-private (което обаче ограничава достъпа до този клас)
* дефинираме `private` или `package-private` конструктори (това прави класа видим, но дава много ограничен контрол върху конкретните типове, които могат да го наследят)

---

### Sealed класове и интерфейси: какъв проблем решават?

#### Решение без sealed класове/интерфейси:

.center[![Non-Sealed Hierarchy](images/03.6-sealed-hierarchy-3.png)]

---

### Sealed класове и интерфейси: какъв проблем решават?

#### Решение със sealed класове/интерфейси:
* намерението да ограничим йерархията от класове е дефинирано _**експлицитно**_ (и лесно)
* разделяме *достъпността* (*accessibility*) от *разширяемостта* (*extensibility*) на класовете

.center[![Sealed Hierarchy](images/03.6-sealed-hierarchy-4.png)]
---

### Sealed класове

- наследниците на `sealed` клас могат да бъдат `final`, `non-sealed` или `sealed`
- наследниците на `sealed` клас могат да бъдат `final`, `sealed` или `non-sealed`
- `sealed` клас може да бъде и абстрактен
- `sealed` класът и неговите permitted класове трябва да са в един пакет
- `sealed` класът и неговите permitted класове **трябва да са в един пакет**
- ако `sealed` класовете са кратки и малък брой, те могат да се дефинират в същия сорс файл като родителския клас
- в този случай, `permits` клаузата може да се пропусне - компилаторът приема за имплицитно permitted класовете в дадения сорс файл

---

### Sealed класове
### Sealed класове: дефиниции

```java
public sealed class Plant permits Herb, Shrub, Climber {}

// sealed класовете декларират, кои класове могат да ги наследяват
public abstract sealed class Shape
permits Circle, Rectangle, Parallelogram, WeirdShape {...}

final class Herb extends Plant {}
// дефиниране на класове - final наследници на sealed клас
public final class Circle extends Shape {...} // OK
public final class Parallelogram extends Shape {...} // OK

non-sealed class Shrub extends Plant {}
// дефиниране на класове - sealed наследници на sealed клас
public sealed class Rectangle extends Shape permits Square {...} // OK
public final class Square extends Rectangle {...} // OK

sealed class Climber extends Plant permits Cucumber{}
// дефиниране на класове - non-sealed наследници на sealed клас
public non-sealed class WeirdShape extends Shape {...} // OK

final class Cucumber extends Climber {}
// не можем да разширяваме йерархията извън зададените ограничения
public class Triangle extends Shape {...} // Compile error
```

---

### Sealed класове и интерфейси

- При `sealed` класовете и интерфейсите, съществува изчерпателен списък от наследниците, който е известен на компилатора, IDE-то и JVM-a, което позволява по-мощен анализ на кода
- например, `instanceof` и casts могат да проверяват цялата йерархия статично
- може да изпозлваме "умен" `switch`, който няма нужда от `default` case, ако всички класове са изброени
---
### Sealed класове и интерфейси

Sealed класове като селектор на switch:
```java
// няма нужда от default case, ако всички позволени класове са изброени
double area = switch (shape) {
case Circle c -> Math.pow(c.radius(), 2) * Math.PI
case Rectangle r -> r.a() * r.b()
};
```
---


### Sealed интерфейси

- `sealed` интерфейсите могат да специфицират, кои интерфейси могат да ги наследяват и кои класове могат да ги имплементират
Expand Down Expand Up @@ -637,11 +696,6 @@ final class Karate implements Kick {}

---

### Нововъведенията в Java в 2021

.center[![Stack vs. heap](images/03.1-favorite-new-java-features.png)]

---

class: center, middle

Expand Down Expand Up @@ -741,6 +795,12 @@ class: center, middle

---

### Какво представляват изключенията?
* Нормални java обекти, целящи да опишат възникналия проблем.
* Инстанции са на "специални" класове, които също имат йерархия (ще я разгледаме по-късно).

---

### Как се генерира ("хвърля") изключение?

```java
Expand Down Expand Up @@ -1016,4 +1076,4 @@ Exception in thread "main" java.lang.NullPointerException:

.font-xl[.ri-github-fill.icon-inline[[fmi/java-course](https://github.com/fmi/java-course)]]

.font-xl[.ri-youtube-fill.icon-inline[[MJT2023](https://www.youtube.com/playlist?list=PLew34f6r0PxyQmWCgCP5gKeoBuzXJxq1w)]]
.font-xl[.ri-youtube-fill.icon-inline[[MJT2024](https://www.youtube.com/watch?v=nUqYohPFCfE&list=PLew34f6r0Pxys4arinMND8JUh7JyXzeMw)]]

0 comments on commit 7f16cdd

Please sign in to comment.