O que são 'get' e 'set' no Swift?

101

Estou aprendendo Swift e lendo The Swift Programming Languageda Apple, não tenho experiência com Objective C (apenas PHP, JS e outros, mas sem Obj C)

Na página 24-25, vejo este código:

//...Class definition stuff...

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

//...Class continues...

Esta parte NÃO é especificada no livro e não consigo entender para que servem.

Alguém pode me explicar o que são get e set ?

Mr.Web
fonte
2
Você leu a página 21 sobre getter / setter. Além disso, os primeiros 30 pgs são um tour pelo Swift e não a documentação completa.
vol7ron
Se você fez C ++, pode co-relacionar essas coisas com as funções de membro getter e setter da classe
CodingOnSteroid

Respostas:

38

Na verdade, isso é explicado logo antes do código:

Além das propriedades simples que são armazenadas, as propriedades podem ter um getter e um setter.

class EquilateralTriangle: NamedShape {
    ...

Quando alguma outra classe deseja obter essa variável de perímetro, eles fazem o seguinte:

let someVar = myTriangle.perimeter

... O que chama isso de:

get{
    return 3.0 * self.sideLength
}

E, portanto, é essencialmente como se o controlador de chamada fizesse isso:

let someVar = 3.0 * myTriangle.sideLength

Quando você define a variável de outro objeto, ela se parece com isto:

myTriangle.perimeter = 100

Que invoca o código no set{}bloco:

set {
    sideLength = newValue / 3.0
}

E então é como se a classe que está definindo a variável tivesse feito isso:

myTriangle.sideLength = 100/3.0

É realmente apenas por conveniência - você pode chamar isso de outro código sem ter que dividir ou multiplicar por 3 o tempo todo, porque isso é feito antes de definir a variável e antes de obter a variável.

Em Swift, podemos ter propriedades que são calculadas quando obtidas e podemos fazer algo quando definidas. Também poderíamos fazer isso em 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;
}
Desfazer
fonte
108

A obtenção e configuração de variáveis ​​dentro das classes refere-se a recuperar ("obter") ou alterar ("definir") seus conteúdos.

Considere uma variável membersde uma classe family. Naturalmente, essa variável precisaria ser um número inteiro, já que uma família nunca pode consistir em dois pontos e algo pessoas.

Portanto, você provavelmente iria em frente definindo a membersvariável assim:

class family {
   var members:Int
}

Isso, no entanto, dará às pessoas que usam essa classe a possibilidade de definir o número de membros da família em algo como 0 ou 1. E, como não existe família de 1 ou 0, isso é lamentável.

É aqui que entram os getters e setters. Dessa forma, você pode decidir por si mesmo como as variáveis ​​podem ser alteradas e quais valores elas podem receber, bem como decidir qual conteúdo elas retornam.

Voltando à nossa aula de família, vamos ter certeza de que ninguém pode definir o membersvalor para nada menos do que 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')
     }
   }
  }
}

Agora podemos acessar a membersvariável como antes, por digitação instanceOfFamily.members, e graças à função setter, também pode configurá-lo de valor como antes, por digitação, por exemplo: instanceOfFamily.members = 3. O que mudou, entretanto, é o fato de que não podemos mais definir essa variável para nada menor que 2.

Observe a introdução da _membersvariável, que é a variável real para armazenar o valor que definimos por meio da membersfunção setter. O original membersagora se tornou uma propriedade computada, o que significa que ele age apenas como uma interface para lidar com nossa variável real.

Markus Buhl
fonte
members==> count, numberOfMembers; var members : Set<Person>??
GoZoner
1
set (newVal) { ... }, newVal está implícito, portanto set { _members = newVal }também está correto.
AndreasHassing
4
Observe que variáveis ​​como _membersdevem ser privadas, caso contrário, o comando instanceOfFamily._members=1seria definido instanceOfFamily.memberscom um valor abaixo de 2
Daniel
Parece que o parâmetro padrão é nomeado newValueem Swift 4 - docs.swift.org/swift-book/LanguageGuide/Properties.html#ID260
Nolan Amy
18

Uma pergunta simples deve ser seguida por uma resposta curta, simples e clara.

  • Quando estamos obtendo um valor da propriedade, ele dispara sua get{}parte.

  • Quando estamos definindo um valor para a propriedade, ela dispara sua set{}parte.

PS. Ao definir um valor para a propriedade, SWIFT cria automaticamente uma constante chamada "newValue" = um valor que estamos definindo. Após um constante "newValue" torna-se acessível na set{}parte da propriedade .

Exemplo:

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
Máxima
fonte
1
é obrigatório atribuir um valor padrão para o membro acessar de fora da classe. Eu tive esse problema corrigido quando atribuí o valor padrão para a classe UserBean: NSObject {var user_id: String? = nil} acessando-o como o seguinte permite ao usuário: UserBean = UserBean () user.user_id = "23232332"
Amr Angry
1

Você deve olhar para Propriedades Computadas

Em seu exemplo de código, perimeteré uma propriedade sem backup de uma variável de classe; em vez disso, seu valor é calculado usando o getmétodo e armazenado por meio do setmétodo - geralmente referido como getter e setter .

Quando você usa essa propriedade desta forma:

var cp = myClass.perimeter

você está invocando o código contido no getbloco de código e quando o usa desta forma:

myClass.perimeter = 5.0

você está chamando o código contido no setbloco de código, onde newValueé preenchido automaticamente com o valor fornecido à direita do operador de atribuição.

As propriedades computadas podem ser lidas e gravadas se um getter e um setter forem especificados, ou somente leitura se apenas o getter for especificado.

Antonio
fonte
0

variável declara e chama assim em uma classe

class X {
    var x: Int = 3

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

//value of x is:  3

agora você deseja programar para tornar o valor padrão de x maior ou igual a 3. Agora, considere o caso hipotético se x for menor que 3, seu programa falhará. então, você quer que as pessoas coloquem 3 ou mais de 3. O Swift facilitou para você e é importante entender essa maneira um pouco avançada de datar o valor da variável porque eles serão amplamente usados ​​no desenvolvimento do iOS. Agora vamos ver como get e set serão usados ​​aqui.

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

se ainda tiver dúvidas, lembre-se, o uso de get e set serve para atualizar qualquer variável da maneira que queremos que seja atualizada. get e set darão a você melhor controle para controlar sua lógica. Ferramenta poderosa, portanto, não facilmente compreensível.

Saran
fonte