Чому я не можу використовувати протокол дозволу в Swift?


80

Я сумніваюся у протоколах Swift щодо використання var та ключових слів {get set} .

З документації Apple :

Якщо протокол вимагає, щоб властивість була доступною для встановлення та встановлення, ця вимога щодо властивості не може бути виконана постійною збереженою властивістю або обчислюваною властивістю лише для читання. Якщо протокол вимагає лише отримання властивості, яку можна отримати, ця вимога може бути задоволена будь-яким видом властивості, і це властивість також може бути встановленою, якщо це корисно для вашого власного коду.

Вимоги до властивостей завжди оголошуються як властивості змінних із префіксом до ключового слова var. Властивості, які можна отримати та встановити, позначаються написом {get set} після оголошення їх типу, а властивості gettable - введенням {get}.

Я не можу зрозуміти, чому я не можу використовувати let . Вар в протоколі тільки з МЕТ не просто нехай ?

Щось на зразок цього:

protocol someProtocol 
{
   var someProperty: String { get }
}

це було б не просто:

protocol someProtocol 
{
   let someProperty: String
}

Мені чогось не вистачає?


9
властивість gettable все ще може змінювати значення - реалізатор протоколу завжди може повертати різні значення, абонент, який викликає протокол, просто не може їх встановити. let, з іншого боку, визначає константу. його можна встановити лише один раз і не може мати іншого значення.
pvg

1
@pvg, чому ти не опублікував це як відповідь?
courteouselk

так, це правильна відповідь тут.
sunshinejr

5
@AntonBronnikov Відповіді на прості запитання часто закінчуються змаганням, хто може набрати найдрібнішу та найменш зрозумілу річ. Щодо дрібниць, простіше просто коментувати. Крім того, лінивий.
pvg

@pvg, я розумію вашу думку. Треба, будь ласка, мати рацію.
courteouselk

Відповіді:


65

"Var у протоколі з лише get не є лише дозволом?" Ні. A letпозначає константу. Але тут справа не в цьому. Розглянемо наступне:

protocol SomeProtocol {
    var someProperty: String { get }
}

class SomeClass : SomeProtocol {

    var someProperty: String = ""

    func cla () {
        someProperty = "asd"
    }
}

let someInstance = SomeClass()

print(someInstance.someProperty) // outputs ""
someInstance.cla()
print(someInstance.someProperty) // outputs "asd"

Протокол вказує, що відповідний клас показує зовні - деяку властивість типу з Stringіменем, somePropertyяку ви можете принаймні отримати.

Якщо протокол вказує, { get }ваш клас може вибрати відповідність через, let someProperty: String = ""але він також може вибрати відповідність за допомогою наведеного вище коду. Якщо, з іншого боку, протокол вказує, що { get set }ви не можете використовувати його letв реалізації, але його також потрібно встановити.

Протокол просто не може визначити, що значення повинно бути постійним - і не повинно, це деталь реалізації, про яку повинен подбати (або вирішити) клас / структура, яка його реалізує.


Озираючись назад, це було настільки просто і очевидно, що в протоколах дозволені лише функції (тоді властивості), але я завжди волію запитувати і вирішувати будь-які сумніви; тепер використання { get set }це зрозуміло як ніколи, ще раз спасибі!
Массімо Полімені

1
Протокол просто не може визначити, що значення повинно бути постійним - також не повинно бути Чому ні? Чому Apple не надала більшої деталізації та дозволила визначати властивості let та var? Або ви кажете, хоча Apple могла б обрати те, що я сказав, натомість вони вирішили, що гнучкість повинна надаватися на рівні реалізації
Мед

46

Різниця між ними

protocol MyProtocol {
    let someProperty: String
}

що не має сенсу - протокол не повинен диктувати, як someProperty визначається / зберігається, лише те, що він доступний як властивість. Це може бути як обчислюване, так і збережене властивість, але це вирішує реалізатор, а не сам протокол.

і

protocol MyProtocol {
    var someProperty: String { get }  // abstract interface
}

struct MyStruct: MyProtocol {
    let someProperty: String  // concrete implementation: stored property
}

struct OtherStruct: MyProtocol {
    let i: Int
    var someProperty: String { return "\(i)" }  // concrete implementation: computed property
}

що цілком дозволено!


1
протокол не повинен диктувати, як somePropertyвизначається / зберігається. Чи не визначає протокол ім'я / тип змінної / має бути встановленим чи ні? Чому Apple не надала більшої деталізації та дозволила визначати властивості let та var?
Мед,

2

Я думаю, що протокол може вимагати, щоб у структурі щось було, але він не може обмежувати функціональність структури або об'єкта. Це не повинно заважати вам робити те, що ви, мабуть, хотіли б робити в коді, наприклад, використання varпротоколу і a letдля реалізації є прийнятним.

protocol MyProtocol {
    var trythis: Int { get }
}

struct MyStructure: MyProtocol {
    let trythis: Int
}
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.