Почему Swift запрещает присваивание self в классе init, но не в протоколе init? - PullRequest
0 голосов
/ 19 января 2019

Мне часто нравится, как в инициализаторах для struct с, enum с и protocol с я могу написать что-то вроде self = someValue. Это замечательно, когда у меня есть некоторые предопределенные значения или я клонирую существующее значение.

Однако этот синтаксис не работает для class es. Я тоже не могу понять почему. Если проблема заключается в двойной инициализации, компилятор Swift знает, если, когда и где я вызываю обозначенные super или self инициализаторы, поэтому он знает, завершил ли я инициализацию этого экземпляра. Если проблема заключается в том, что я еще не вызвал назначенный инициализатор, тогда все должно быть в порядке, потому что я бы просто сделал этот экземпляр ссылкой на другой (указатель 2 vars 1). Если проблема заключается в том, что одновременный доступ мог вызвать инициализацию self, то это бессмыслица, потому что мы в инициализаторе, а Swift инициализаторы не восприимчивы к этому .

И после всего, что я обнаружил, я могу обойти это с помощью одноразового протокола:

class MyClass {
    let content: String

    init(content: String) {
        self.content = content
    }

    convenience init(from1 other: MyClass) {
        self = other // Cannot assign to value: 'self' is immutable
    }
}



protocol MyProto {}

extension MyClass: MyProto {}



extension MyProto {

    init(from2 other: Self) {
        self = other
    }
}



let foo = MyClass(content: "Foo")

print(MyClass(from1: foo)) // Never would've compiled in the first place
print(MyClass(from2: foo)) // Perfectly OK!

Так почему же это запрещено в общем использовании, но разрешено в расширениях протокола?

1 Ответ

0 голосов
/ 19 января 2019

Кажется, что в настоящее время он ведет себя как ожидалось.

Вся проблема обсуждалась на быстрых форумах: Назначение себя в расширениях протокола

В последний раз, когда эта странность возникла во внутренних дискуссиях, у некоторых из нас возникла мысль, что, возможно, стоит запретить классам соответствовать протоколам с изменяющимися требованиями в целом. Если подумать, это имеет некоторый смысл - кажется, что было бы довольно сложно написать код, который может работать как с изменяемыми значениями, так и с изменяемыми ссылками в целом, поскольку последние не имеют семантики значений:

var x = y
x.mutatingProtocolRequirement()
// did y change too?

Однако дискуссия вроде провалилась.

...