On branch main

modified:   src/ch08.md
This commit is contained in:
zed
2023-11-18 21:23:08 +03:00
parent ff65b73209
commit d773a99ac5

View File

@@ -357,9 +357,9 @@ ptr_info.Pointer.child.writeAll(self, data);
## Использование маркированных объединений
...
Вот рабочий полноценный пример:
В качестве более простой альтернативы описанным схемам для эмуляции
интерфейсов можно применять маркированные объединения, вот полноценный
рабочий пример:
```zig
const std = @import("std");
@@ -391,3 +391,32 @@ pub fn main() !void {
}
```
Напомним, что когда в `switch` используется переменная, представляющая
собой маркированное объединение, захваченные значения (в примере
`|file|`) всегда имеют правильный тип (для примера это `File`).
Минусом такого подхода является то, что нужно заранее знать все возможные
реализации, поэтому он не подходит, например, для создания интерфейсов,
реализации которых могли бы создавать третьи стороны. Каждая возможная
реализация должна быть включена в объединение.
Если интерфейс используется только внутри какого-то приложения,
это ограничение роли не играет. Вы можете построить, к примеру,
объединение `Cache`, которое будет включать в себя все нужные
реализации, например, `InMemory`, `Redis` и `Postgresql`. Если
появляются новые механизмы, Вы просто обновляете объединение.
Во многих случаях интерфейс будет вызывать функции с реализациями
непосредственно. Для таких случаев можно использовать специальный
синтаксис, `inline else`:
```zig
switch (self) {
.null => {}, // do nothing
inline else => |impl| return impl.writeAll(data),
}
```
Такой оборот `else` автоматически разворачивается,
то есть для каждого варианта получается правильный тип `impl`.