Следите за новинками
в нашем Telegram канале. Жми, чтобы подписаться:)
⊗dtSpJsSd 116 of 224 menu
◀ ▶

Несколько форм в Dart

Одно поле может хранить разные варианты данных: успех с числом или ошибка с текстом. Ключевое слово sealed на базовом классе перечисляет допустимые формы через final подклассы, а запись и чтение JSON задают вручную в методах toJson и фабрике по полю type.

Для JSON удобно добавить служебный ключ type - дискриминатор, по которому при чтении выбирают конкретный подкласс. Короткая метка вроде "paid" задается в коде записи и разбора:

sealed class PayReply {} final class Paid extends PayReply { Paid(this.amount); final int amount; } final class Declined extends PayReply { Declined(this.reason); final String reason; } Map<String, Object?> payReplyToJson(PayReply reply) { return switch (reply) { Paid(:final amount) => { 'type': 'paid', 'amount': amount, }, Declined(:final reason) => { 'type': 'declined', 'reason': reason, }, }; } PayReply payReplyFromJson(Map<String, Object?> json) { return switch (json['type']) { 'paid' => Paid(json['amount'] as int), 'declined' => Declined(json['reason'] as String), _ => Declined(json['type'] as String), }; }

Запись значения типа PayReply включает "type":"paid" или "type":"declined" рядом с полями варианта:

import 'dart:convert'; sealed class PayReply {} final class Paid extends PayReply { Paid(this.amount); final int amount; } final class Declined extends PayReply { Declined(this.reason); final String reason; } Map<String, Object?> payReplyToJson(PayReply reply) { return switch (reply) { Paid(:final amount) => { 'type': 'paid', 'amount': amount, }, Declined(:final reason) => { 'type': 'declined', 'reason': reason, }, }; } PayReply payReplyFromJson(Map<String, Object?> json) { return switch (json['type']) { 'paid' => Paid(json['amount'] as int), 'declined' => Declined(json['reason'] as String), _ => Declined(json['type'] as String), }; } PayReply ok = Paid(900); var text = jsonEncode(payReplyToJson(ok)); print(text); var raw = jsonDecode(text); if (raw is Map<String, Object?>) { var back = payReplyFromJson(raw); print(back); }

После разбора статический тип снова PayReply, а фактическая форма определяется при проверке ветки switch. Так повторяется идея закрытой иерархии из раздела об ООП, но здесь ветку выбирают по строке type в JSON.

Опишите sealed класс InboxEvent с вариантами Opened (поле msgId, имя "opened") и Archived (поле folder, имя "archived"). Запишите событие Opened с идентификатором 7 в JSON и выведите строку.

Разберите текст {"type":"archived","folder":"2024"} в InboxEvent и выведите имя папки из восстановленного варианта.

← →
↑
Мы используем cookie для работы сайта, аналитики и персонализации. Обработка данных происходит согласно Политике конфиденциальности.
принять все настроить отклонить