Как стать автором
Обновить

Комментарии 17

Непонятно стоило ли объединять enum'ы и variant'ы в одну сущность.
ИМХО, стоило эти вещи оставить отдельно: перечисления — как низкоуровневая конструкция, совместимая с int, варианты — как алгебраический тип данных («тип-сумма») со всеми фичами, присущими такому типу.
Почему перечисления предполагается совмещать именно с int'ом? Какие недостатки у Свифтового подхода?
В C и C++ так делают, enum там — это int, даже по стандарту, кажется, так. Наверное недостаток в том что свифтовский enum нельзя приводить к int, ведь там могут быть эти самые «Associated Values».
В C и C++ так делают,

И? Надо смотреть на преимущества, а не просто повторять. Иначе зачем вообще нужен Swift — можно дальше на С или С++ писать.


Ну и в С++ "по стандарту" не (обязательно) int — это деталь реализации. Более того, тип можно и самому задать.


Насчёт невозможности приводить — это далеко не всегда нужно. За Swift не скажу, зато могу сказать за Rust, где enumы похожим образом выглядят. Там можно указать repr© — тогда (если это возможно) такой enum будет совместим с C.

Я сам в основном согласен и сам знаю как в Rust. Просто растолковал точку зрения стартера ветки, и обозначил это словом «наверное».
Ну потому что перечисления это более примитивная сущность чем варианты. Также потому что некоторые типы все-же должны быть POD, например для работы с бинарными форматами или сетевыми протоколами.
Приведу вот такой пример. Можно отказаться от разнообразных числовых типов (int, short, long, unsigned int, float, double и т.д.) и перейти к единому числовому типу, скажем «numeric». Неограниченной длины, любой точности. Возможно это будет удобно. Но это будет сущность более сложная чем базовые типы, и безусловно, отказ от базовых типов уменьшит хакерскую мощь языка. Но в то же время добавление высокоуровневых вариантов с сохранением низкоуровневых перечислений не только не уменьшит, но и увеличит хакерские возможности языка программирования.
а как же паттерны, все дела?
Какие именно дела имеются в виду?
в паттернах не очень разбираюсь, но наверное — Стратегия
Цель статьи — не показать способы решения задачи, а продемонстрировать одну из возможностей языка.

Про Стратегию. Чуть ниже обсуждают похожее решение. Конечно же, можно использовать и её, ни в коем случае не говорю, что нужно только так и описывать платёжные модели. Это просто пример. :-)
А при чем здесь блог .NET? Или я чего-то не понимаю?
Упс :) Спасибо!
Прошу прощение, если вопрос глупый, на Swift не программировал. А нельзя просто сделать базовый класс Payment с абстрактным методом Execute() (или другими общими методами), унаследовать от него CashPayment, CardPayment, GiftPayment, PayPalPayment и любое количество других вариантов оплаты?
Не автор и тоже никогда не использовал Swift, но попробую ответить, т.к. стыкался с подобным. Если сделать по предложенному вами варианту, и если этот код является не частью закрытого энтерпрайз-софта, а, к примеру, библиотекой с открытым АПИ, то сторонний код, использующий библиотеку, сможет сделать свою реализацию базового абстрактного класса Payment (или интерфейса IPayment, не важно), которая (своя реализация) может поломать осн. бизнес-логику. Т.е. её можно будет подсунуть вместо предопределённых {CashPayment, CardPayment, GiftPayment, PayPalPayment} в какой-то метод библиотеки, принимающий на вход Payment, и поломать там что-то внутри.
Да так можно сделать на Swift, но начиная с Swift 3 описанная проблема тоже решается — появилось дополнительное ключевое слово `open`, которое отличается от `public`.
Все тот-же пример:
Создается библиотека с открытым АПИ. В ней есть класс Payment и в ней реализованы: CashPayment, CardPayment, GiftPayment, PayPalPayment.
Если разработчик библиотеки хочет дать возможность сторонним разработчикам наследоваться от всех этих классов, то их стоит объявить `open`.
Если только от Payment то все будут `public`, а Payment `open`.
И чтобы закрыть полностью данную возможность, надо все объявить `public`.

То есть `public` позволяет наследовать внутри библиотеки, но не позволяет наследоваться за пределами библиотеки, а `open` позволяет наследоваться и внутри и за пределами.

Поэтому описанная проблема, имеет решение на Swift 3.0

Я думаю, пример в статье стоит рассматривать больше с «клиентской» стороны.


В предполагаемом мобильном приложении на языке Swift не будет никакой бизнес-логики, типа «Провести оплату». Т.е. наверняка будет какой-то вызов API для проведения оплаты, чтобы сервер провёл эту операцию, но реализовывать метод Execute() на стороне клиента не придётся.


На стороне клиента придётся реализовывать ленту с историей проведенных операций оплаты, в которой должны содержаться сущности разного рода: Cash Payment, Card Payment, PayPal Payment и другие. И в данной ситуации важным является именно то, как организовать модель данных, полученных от сервера, чтобы их можно было единообразно отобразить в единой ленте.


И перечисления в данной ситуации играют роль логических ограничений. Например, у сущности PaymentWithEnums физически не может быть воплощения, в котором будет содержаться и срок истечения карты expirationDate, и transactionAuthCode.

Самая большой напряг который можно встретить с перечеслениями и ассоциативными значениями это отсутствие опыта проектирования потока иммутабельных данных, то есть если вам нужно чтото мутировать надо всю структуру данных пересобрать с новым значением какого то поля
Зарегистрируйтесь на Хабре, чтобы оставить комментарий