On branch main
modified: src/ch08.md
This commit is contained in:
35
src/ch08.md
35
src/ch08.md
@@ -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`.
|
||||
|
||||
Reference in New Issue
Block a user