iOS Swift4, как защитить вычисленное свойство, определенное в интерфейсе, от присвоения?

Я отлаживаю некоторые плохо написанные модульные тесты для класса из унаследованной базы кода. Я вижу, что разработчик неправильно проверяет вычисляемое свойство. Я хочу понять, как обеспечить соблюдение моих userEnabledFeature быть прочитанным только в классе Fake.

Почему протокол реализации класса с вычисляемым свойством может перезаписать вычисленное свойство и сделать его доступным для записи?

public protocol FeatureManager {
    var userEnabledFeature : Bool { get }
}

public class FakeFeatureManagerForTesting: FeatureManager {
    public var userEnabledFeature = false //is this legal? Why is compiler not complaining?

    public func updateUserEnabledFeature(enabled: Bool){
        //this should not be possible - how do I prevent overwriting computed property?
        userEnabledFeature = enabled
    }
}

ActualFeatureManagerClass {
    public var userEnabledFeature: Bool {
        if featureManager.cachedFeatures.filter { $0.enabled == true}
        {
            //do more checks, return true or false
        }
        return false //default
    }
}

1 ответ

public class FakeFeatureManagerForTesting: FeatureManager {
  public var userEnabledFeature = false //is this legal? Why is compiler not complaining?
}

Протокол говорит, что члены, которые соответствуют ему, должны иметь Bool имущество userEnabledFeature это может быть прочитано, не то, что это свойство только для чтения. Однако, если у вас есть переменная с типом протокола, она не позволит вам присвоить свойство, даже если значение переменной является реализацией, для которой оно также доступно для записи.

Протокол определяет не то, как он реализован (если его вычисляемое свойство, хранимое свойство и т. Д.), А какова его подпись и должен ли он быть доступен только для чтения или иметь права на запись. Если вы отметите его как доступный только для чтения, реализация все равно может сделать запись доступной для записи, так как в этом случае протокол не заботится о доступе на запись.

Вы можете получить вычисляемое свойство следующим образом:

public class FakeFeatureManagerForTesting: FeatureManager {
  public var userEnabledFeature: Bool { 
    // do some work here and return value or fallback to false
    return false
  }
}

С другой стороны, вы также можете иметь только закрытое настраиваемое свойство, которое можно изменить только из файла или класса / структуры:

public class FakeFeatureManagerForTesting: FeatureManager {
  public private(set) var userEnabledFeature = false

  public func updateUserEnabledFeature(enabled: Bool) {
    userEnabledFeature = enabled // will work just fine
  }
}

let manager = FakeFeatureManagerForTesting()
manager.updateUserEnabledFeature(enabled: true) // will work
manager.userEnabledFeature = true // won't compile, because modifying is allowed privately only
Другие вопросы по тегам