Pull to refresh

Comments 22

ваше расширение будет доступно для всех опциональных типов. Выглядит не очень хорошо: (...) Однако компилятор защитит вас и не скомпилирует этот код.

То есть это не особенность языка, и ничего там не будет доступно, а просто просчёт в системе автодополнения, которая не была готова к таким фокусам(?)

Мне тоже не понятен этот момент. Там же чётко написано ограничение


extension Optional where Wrapped == String { ...

Я так же могу в котлин написать:


class Wrapper<T>(val t: T)

fun Wrapper<String>.printMe() {
    println(t)
}

Однако компилятор защитит вас и не скомпилирует этот код. Но если вы добавите больше таких расширений — ваша автоподсказка будет забита мусором.

В котлине автоподсказка мусором не забивается. Может, виновата ide, а не язык?

Кстати, сколько помню, стандартный joined, который для стокового Sequence, у меня в Xcode ни разу не выводился для коллекций других типов.

кстати, для
extension Optional where Wrapped == String {
    func orEmpty() -> String {
        switch self {
        case .some(let value):
            return value
        default:
            return ""
        }
    }
}

можно было оставить и изначальную реализацию orEmpty()
extension Optional where Wrapped == String {
    func orEmpty() -> String {
        return self ?? ""
    }
}

Точно. Наверное автор оригинального поста так написал, чтоб было более понятно что там в опционале "под капотом" происходит. :)

Это мое больное воображение, или значки в начале правда увеличиваются?

Не обратил внимания, но да. Таки оптическая иллюзия имеет место быть. :)

UFO just landed and posted this here
А это совсем не то, чего я хотел.

Именно — передача по ссылке/значению очень субъективно. Лично на мой взгляд, передача по ссылке по-умолчанию на порядок удобнее и логичнее. Особенно если мои дата-классы иммутабельные. А если надо скопировать, то есть метод `copy` из коробки. Конечно бывают кейзы, когда хотелось бы иметь value-типы и в жвм возможно их скоро завезут, но таких случаев значительно меньше, чем те, что покрываются обычными дата-классами.

Вы можете создать свой протокол и расширение для класса, чтоб соответствовать этому протоколу.

Да это приятная фича языка поддерживаемая платформой (в отличии от жвм), только примеры про неё ничего не говорят.
Это может быть сложно даже с Mockito

Серьезно? Если у вас есть интерфейс, нет никакой проблемы замокировать его. С файналами не так всё просто конечно, но пример совершенно это не показывает.
Они отличаются только названием и, конечно же, sealed-класс передается по ссылке, а перечисление в Swift — по значению.

Сначала опять про ссылки и значения. Для перечислений нет никакой разницы, передавать адрес константы или её номер. А для sealed-классов, та же дилемма, что и в первом пункте. И да, различий нет уж и много, но они есть.

Да, про ссылки/значения — холивар может быть вечным. Вот, например, есть у вас объекты типа «монитор», и у них есть свойство «разрешение». Это свойство состоит из двух полей: ширина, высота. Вопрос: какого типа должно быть свойство «разрешение»? Класс или структура? Должно ли оно передаваться по ссылке или по значению. И если у меня есть два монитора с одинаковым разрешением, то меняя разрешение на одном из них ожидаю ли я, что оно изменится и на втором? :)


Про Мокито вы невнимательно прочитали. Речь о невозможности замокать именно final-класс, а не интерфейс. И в этом и преимущество Свифта: можно даже final-класс подписать на свой протокол (интерфейс) и мокать уже протокол (интерфейс). Главное, чтоб в протоколе (интерфейсе) сигнатуры методов совпадали с тем, что объявлено в final-классе.

да, прошу прощения, неправильно понял, всё верно про возможность мокировать по тайпклассу. Очень это приятная фича, которой нет в жвм платформе. Есть реализация в форке котлина, но у этого всего плохая совместимость с джавой и сложность в корректной поддержке во всех аспектах, так что не факт, что тайпклассы появятся даже как экспериментальная фича в котлине

Ну всё-таки в Mockito 2 final классы мокаются без проблем.

Лучше использовать эту фичу только для старого-старого кода, когда нет возможности сделать нормальную архитектуру.

Передача по ссылке или значению — это архаизмы реализаций компиляторов и языков прошлых лет, когда это имело смысл. На сегодняшний день важно лишь, что описываемая сущность является мутабельной или иммутабельной. В случае иммутабельной сущности нам не важно передается ли она по значению или по ссылке и где физически она находится в памяти — это уже внутренние проблемы компилятора и рантайма. При операциях с иммутабельными сущностями каждый раз создается новый экземпляр. Таким образом иммутабельные классы полностью идентичны value type (подразумевается наличие equals()/hashCode()).


В случае же мутабельной сущности, мы имеем каждый раз дело с экземпляром, занимающим определенное место в памяти, и поэтому осознанно работаем с ним по ссылке (некоему хэндлу, если угодно). Для передачи информации о внутреннем состоянии мутабельного объекта вовне есть два способа: хороший — обернуть его иммутабельным врапером, либо плохой: просто сделать defensive copy и отдать на растерзание. Структуры в Свифте — это просто реализация defencive copying по умолчанию, тогда как в Котлине это нужно делать въявную. Мне кажется не стоило делать отдельный класс объектов языка только лишь для реализации одного паттерна. Тем более, что изначально структуры (записи) в языках программирования означали немножко другое и появились задолго до классов.

UFO just landed and posted this here

Необходимость мокать final классы, говорит о просветах в дизайне.

Не очень понятно, за что минусы. За стиль? Или кто-то полагает, что моки из final классов — это хорошо?
Не минусовал, но конкретно я бы предпочел мокать final класс, чем создавать бесполезный интерфейс с одной реализацией, только для того, чтобы мокать его в тестах.

То есть я бы сказал, что просветом в дизайне являются скорее такие интерфейсы, если на их существование нет никакой другой весомой причины (например, скрыть платформо-зависимые компоненты).

Ну а открывать класс только для того, чтобы его можно было мокнуть без Mockito 2 — тоже не сильно хорошо.
Ну вот навскидку:
  • Отделение контракта чтобы не тащить за собой зависимости реализации.
  • Раздельное управление API и реализацией.
  • Добавление явных декораторов вместо неявных аспектов.
  • Улучшение читаемости API.
  • Сокрытие платформозависимого компонента, конечно же.

Можно, наверное, еще подумать, зачем может быть нужен интерфейс с единственной
реализацией, но и приведенного должно быть достаточно.

Конечно, легко себе вообразить проект, где перечисленные выше причины вообще никогда не возникнут, но в моем текущем проекте и во всех предыдущих за последние лет 6 наличие интерфейса практически у любого сервиса подразумевалось по умолчанию.

Не могу плюсануть комментарий (видимо есть ограничение по времени), но вы не один)

А давайте еще минусанем, за попытку донести мысль об абсурдности поста
Sign up to leave a comment.

Articles