Расширение протокола, изменяющаяся функция

Я использую swift 2.0, у меня есть протокол и расширение протокола для создания реализации метода по умолчанию, код выглядит следующим образом:

protocol ColorImpressionableProtocol {

    var lightAccentColor: UIColor? {get set}
    var accentColor: UIColor? {get set}
    var darkAccentColor: UIColor? {get set}
    var specialTextColor: UIColor? {get set}

    mutating func adoptColorsFromImpresion(impresion: ColorImpressionableProtocol?)
}

extension ColorImpressionableProtocol {

    mutating func adoptColorsFromImpresion(impresion: ColorImpressionableProtocol?){
        lightAccentColor = impresion?.lightAccentColor
        accentColor = impresion?.accentColor
        darkAccentColor = impresion?.darkAccentColor
        specialTextColor = impresion?.specialTextColor
    }
}

Позже я в своем коде пытаюсь вызвать этот метод и получаю сообщение об ошибке:

«невозможно использовать изменяющийся член для неизменяемого значения:« я »неизменен»

Код выглядит следующим образом:

init(impresion: ColorImpressionableProtocol?){
        super.init(nibName: nil, bundle: nil)
        adoptColorsFromImpresion(impresion)
}

Единственное, о чем я могу думать, так это о том, что «Я» в данном случае — это протокол, а не класс. Однако мне нужно что-то упустить, чтобы эта концепция работала. Реализация по умолчанию метода, определенного протоколом, который редактирует значения, также определенные тем же протоколом.

Спасибо за помощь и время :)


person CWineland    schedule 09.09.2015    source источник


Ответы (2)


Если вы собираетесь использовать протокол только для классов, вы можете сделать его протоколом класса (и удалить ключевое слово mutating):

protocol ColorImpressionableProtocol : class {

    // ...

    func adoptColorsFromImpresion(impresion: ColorImpressionableProtocol?)
}

Затем

init(impresion: ColorImpressionableProtocol?){
    super.init(nibName: nil, bundle: nil)
    adoptColorsFromImpresion(impresion)
}

компилируется без проблем.

person Martin R    schedule 09.09.2015
comment
Я считаю, что это правильный синтаксис для того, что я пытаюсь сделать, Perfecto! Спасибо - person CWineland; 10.09.2015
comment
Я должен спросить об этом ради здравомыслия ... что еще может реализовать протокол, кроме класса, от чего это защищает? Я просто не вижу никакого другого результата, кроме класса, соответствующего ему. - person CWineland; 10.09.2015
comment
@CWineland: протоколы также могут быть реализованы структурой. - person Martin R; 10.09.2015

Вы принимаете этот протокол в классе, поэтому self (который является ссылочным типом) неизменяем. Компилятор ожидает, что self будет изменяемым из-за изменяемого метода, объявленного в протоколе. Вот почему вы получаете эту ошибку.

Возможные решения:

1) Реализовать неизменяемую версию метода, в котором принимается протокол. то есть: реализовать метод в принятии класса вместо расширения протокола.

class MyClass : ColorImpressionableProtocol {

   func adoptColorsFromImpresion(impresion: ColorImpressionableProtocol?){
        lightAccentColor = impresion?.lightAccentColor
        accentColor = impresion?.accentColor
        darkAccentColor = impresion?.darkAccentColor
        specialTextColor = impresion?.specialTextColor
    }
}

2) Сделайте протокол протоколом только класса. Таким образом мы можем удалить ключевое слово mutating. Это самое простое решение, но его можно использовать только в классе.

Чтобы сделать только класс протокола:

protocol MyProtocolName : AnyObject { }
OR
protocol MyProtocolName : class { }

3) Убедитесь, что только типы значений принимают этот протокол. Это может быть полезно не во всех сценариях.

Здесь подробное объяснение и решение для этого случая.

person Abhijith    schedule 20.07.2017