Что такое "получить" и "установить" в Swift?

102

Я изучаю Swift, и я читаю The Swift Programming Languageиз Apple, у меня нет опыта Objective C (только PHP, JS и другие, но не Obj C)

На странице 24-25 я вижу этот код:

//...Class definition stuff...

var perimeter: Double {
    get {
        return 3.0 * sideLength
    }
    set {
        sideLength = newValue / 3.0
    }
}

//...Class continues...

Эта часть НЕ указана в книге, и я не могу понять, для чего они нужны.

Может ли кто-нибудь объяснить мне, что такое get и set ?

Мистер Веб
источник
2
Вы читали стр.21 о геттере / сеттере? Кроме того, первые 30 страниц или около того - это экскурсия по Swift, а не полная документация.
vol7ron
Если вы написали C ++, вы можете связать этот материал с функциями-членами класса getter и setter
CodingOnSteroid

Ответы:

38

На самом деле это объясняется прямо перед кодом:

В дополнение к простым сохраняемым свойствам, свойства могут иметь геттер и сеттер.

class EquilateralTriangle: NamedShape {
    ...

Когда какой-то другой класс хочет получить эту переменную периметра, они делают следующее:

let someVar = myTriangle.perimeter

... Что вызывает это:

get{
    return 3.0 * self.sideLength
}

По сути, это похоже на то, как если бы вызывающий контроллер сделал это:

let someVar = 3.0 * myTriangle.sideLength

Когда вы устанавливаете переменную из другого объекта, это выглядит так:

myTriangle.perimeter = 100

Что вызывает код в set{}блоке:

set {
    sideLength = newValue / 3.0
}

И это как если бы класс, устанавливающий переменную, сделал это:

myTriangle.sideLength = 100/3.0

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

В Swift у нас могут быть свойства, которые вычисляются при получении и могут что-то делать при установке. Мы могли бы сделать это и в Objective-C:

// .h
@property (nonatomic) double perimeter;

//.m

- (double)perimeter
{
    return self.sideLength * 3.0;
}
- (void)setPerimeter:(double)perimeter
{
    self.perimeter = perimeter; // In Swift, this is done automatically.
    self.sideLength = perimeter / 3.0;
}
Отменить
источник
108

Получение и установка переменных в классах означает либо получение («получение»), либо изменение («установку») их содержимого.

Рассмотрим переменную membersкласса family. Естественно, эта переменная должна быть целым числом, поскольку семья никогда не может состоять из двух или более человек.

Итак, вы, вероятно, определили бы membersпеременную следующим образом:

class family {
   var members:Int
}

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

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

Возвращаясь к нашему семейному классу, давайте убедимся, что никто не может установить membersзначение меньше 2:

class family {
  var _members:Int = 2
  var members:Int {
   get {
     return _members
   }
   set (newVal) {
     if newVal >= 2 {
       _members = newVal
     } else {
       println('error: cannot have family with less than 2 members')
     }
   }
  }
}

Теперь мы можем получить доступ к membersпеременной , как и прежде, набрав instanceOfFamily.members, а благодаря функции сеттер, мы можем установить его значение , как и прежде, набрав, например: instanceOfFamily.members = 3. Что изменилось, так это то, что мы больше не можем устанавливать для этой переменной значение меньше 2.

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

Маркус Буль
источник
members==> count, numberOfMembers; var members : Set<Person>??
GoZoner
1
set (newVal) { ... }, подразумевается newVal, так что set { _members = newVal }это тоже правильно.
AndreasHassing
4
Обратите внимание, что такие переменные _membersдолжны быть закрытыми, иначе команда instanceOfFamily._members=1установила instanceOfFamily.membersбы значение ниже 2
Даниэль
Похоже, параметр по умолчанию назван newValueв Swift 4 - docs.swift.org/swift-book/LanguageGuide/Properties.html#ID260
Нолан Эми
19

За простым вопросом должен следовать короткий, простой и ясный ответ.

  • Когда мы получаем значение свойства, оно запускает свою get{}часть.

  • Когда мы устанавливаем значение для свойства, оно запускает свою set{}часть.

PS. При установке значения для свойства SWIFT автоматически создает константу с именем «newValue» = значение, которое мы устанавливаем. После того, как в части свойства становится доступной константа newValue set{}.

Пример:

var A:Int = 0
var B:Int = 0

var C:Int {
get {return 1}
set {print("Recived new value", newValue, " and stored into 'B' ")
     B = newValue
     }
}

//When we are getting a value of C it fires get{} part of C property
A = C 
A            //Now A = 1

//When we are setting a value to C it fires set{} part of C property
C = 2
B            //Now B = 2
Максим
источник
1
обязательно ли назначать значение по умолчанию для члена, к которому будет осуществляться доступ извне класса. У меня эта проблема была исправлена, когда я присвоил ей значение по умолчанию class UserBean: NSObject {var user_id: String? = nil} доступ к нему, как показано ниже, let user: UserBean = UserBean () user.user_id = "23232332"
Amr Angry
2

Вы должны посмотреть на вычисленные свойства

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

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

var cp = myClass.perimeter

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

myClass.perimeter = 5.0

вы вызываете код, содержащийся в setблоке кода, newValueкоторый автоматически заполняется значением, указанным справа от оператора присваивания.

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

Антонио
источник
0

переменная объявляет и вызывает такой же вызов в классе

class X {
    var x: Int = 3

}
var y = X()
print("value of x is: ", y.x)

//value of x is:  3

Теперь вы хотите, чтобы программа сделала значение x по умолчанию больше или равным 3. Теперь рассмотрим гипотетический случай, если x меньше 3, ваша программа завершится ошибкой. Итак, вы хотите, чтобы люди ставили 3 или более 3. Swift упростил вам задачу, и важно понимать этот прогрессивный способ датировки значения переменной, потому что они будут широко использоваться при разработке iOS. Теперь посмотрим, как здесь будут использоваться get и set.

class X {
    var _x: Int = 3
    var x: Int {
        get {
            return _x
        }
        set(newVal) {  //set always take 1 argument
            if newVal >= 3 {
             _x = newVal //updating _x with the input value by the user
            print("new value is: ", _x)
            }
            else {
                print("error must be greater than 3")
            }
        }
    }
}
let y = X()
y.x = 1
print(y.x) //error must be greater than 3
y.x = 8 // //new value is: 8

если у вас все еще есть сомнения, просто помните, что использование get и set заключается в обновлении любой переменной так, как мы хотим, чтобы она обновлялась. get and set даст вам лучший контроль над вашей логикой. Мощный инструмент, следовательно, непонятен.

саран
источник