'Get' và 'set' trong Swift là gì?


101

Tôi đang học Swift và tôi đang đọc The Swift Programming Languagetừ Apple, tôi không có kiến ​​thức về Objective C (chỉ PHP, JS và các thứ khác nhưng không có obj C)

Trên trang 24-25, tôi thấy mã này:

//...Class definition stuff...

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

//...Class continues...

Phần này KHÔNG được nêu rõ trong sách và tôi không thể hiểu những điều đó để làm gì.

Bất cứ ai có thể giải thích cho tôi những gì nhận đượcthiết lập là gì?


2
Bạn đã đọc trang 21 về getter / setter. Ngoài ra, 30 pgs đầu tiên hoặc lâu hơn là một chuyến tham quan Swift chứ không phải tài liệu đầy đủ.
vol7ron

Nếu bạn đã làm C ++ bạn có thể cùng liên hệ cụ này với các chức năng getter và setter thành viên của lớp
CodingOnSteroid

Câu trả lời:


38

Điều đó thực sự được giải thích ngay trước mã:

Ngoài các thuộc tính đơn giản được lưu trữ, các thuộc tính có thể có một getter và một setter.

class EquilateralTriangle: NamedShape {
    ...

Khi một số lớp khác muốn nhận được biến chu vi đó, họ thực hiện điều này:

let someVar = myTriangle.perimeter

... Cái này gọi là:

get{
    return 3.0 * self.sideLength
}

Và do đó về cơ bản nó giống như nếu bộ điều khiển cuộc gọi đã làm điều này:

let someVar = 3.0 * myTriangle.sideLength

Khi bạn đặt biến từ một đối tượng khác, nó trông giống như sau:

myTriangle.perimeter = 100

Lệnh nào gọi mã trong set{}khối:

set {
    sideLength = newValue / 3.0
}

Và vì vậy nó giống như nếu lớp thiết lập biến đã thực hiện điều này:

myTriangle.sideLength = 100/3.0

Nó thực sự chỉ để thuận tiện - bạn có thể gọi mã này từ mã khác mà không cần phải chia cho hoặc nhân 3 mọi lúc, bởi vì điều đó được thực hiện ngay trước khi đặt biến và ngay trước khi bạn lấy biến.

Trong Swift, chúng ta có thể có các thuộc tính được tính toán khi nhận và có thể thực hiện điều gì đó khi được thiết lập. Chúng tôi cũng có thể làm điều này trong 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

Việc lấy và thiết lập các biến trong các lớp đề cập đến việc truy xuất ("nhận") hoặc thay đổi ("thiết lập") nội dung của chúng.

Hãy xem xét một biến memberscủa một lớp family. Đương nhiên, biến này cần phải là một số nguyên, vì một gia đình không bao giờ có thể bao gồm hai người một điểm.

Vì vậy, bạn có thể sẽ tiếp tục bằng cách xác định membersbiến như sau:

class family {
   var members:Int
}

Tuy nhiên, điều này sẽ cung cấp cho những người sử dụng lớp này khả năng đặt số lượng thành viên trong gia đình là 0 hoặc 1. Và vì không có thứ gì gọi là họ 1 hoặc 0, điều này khá đáng tiếc.

Đây là nơi các getters và setters đi vào. Bằng cách này, bạn có thể tự quyết định cách các biến có thể được thay đổi và giá trị nào mà chúng có thể nhận được cũng như quyết định nội dung mà chúng trả về.

Quay trở lại lớp gia đình của chúng ta, hãy đảm bảo rằng không ai có thể đặt membersgiá trị thành bất kỳ giá trị nào nhỏ hơn 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')
     }
   }
  }
}

Bây giờ chúng ta có thể truy cập vào membersbiến như trước, bằng cách gõ instanceOfFamily.members, và nhờ vào chức năng setter, chúng tôi cũng có thể thiết lập giá trị của nó như trước, bằng cách gõ, ví dụ: instanceOfFamily.members = 3. Tuy nhiên, điều đã thay đổi là chúng ta không thể đặt biến này thành bất kỳ giá trị nào nhỏ hơn 2 nữa.

Lưu ý phần giới thiệu của _membersbiến, là biến thực để lưu giá trị mà chúng ta đặt thông qua membershàm setter. Bản gốc membersbây giờ đã trở thành một thuộc tính được tính toán, có nghĩa là nó chỉ hoạt động như một giao diện để xử lý biến thực tế của chúng ta.


members==> count, numberOfMembers; var members : Set<Person>??
GoZoner

1
set (newVal) { ... }, newVal được ngụ ý, vì vậy set { _members = newVal }cũng chính xác.
AndreasHassing

4
Lưu ý rằng các biến như _membersphải là riêng tư, nếu không lệnh instanceOfFamily._members=1sẽ được đặt thành instanceOfFamily.membersgiá trị dưới 2
Daniel

Có vẻ như thông số mặc định được đặt tên newValuetrong Swift 4 - docs.swift.org/swift-book/LanguageGuide/Properties.html#ID260
Nolan Amy

18

Một câu hỏi đơn giản nên được theo sau bởi một câu trả lời ngắn gọn, đơn giản và rõ ràng.

  • Khi chúng ta nhận được một giá trị của tài sản, nó sẽ đốt cháy get{}một phần của nó .

  • Khi chúng tôi đặt một giá trị cho thuộc tính, nó sẽ kích hoạt set{}phần của nó .

Tái bút. Khi đặt giá trị cho thuộc tính, SWIFT sẽ tự động tạo một hằng số có tên là "newValue" = một giá trị mà chúng tôi đang đặt. Sau khi một hằng số "newValue" có thể truy cập được trong set{}phần của thuộc tính.

Thí dụ:

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
có bắt buộc phải gán một giá trị mặc định cho thành viên để truy cập từ bên ngoài lớp không. Tôi đã khắc phục sự cố này khi tôi gán giá trị mặc định cho lớp UserBean: NSObject {var user_id: String? = nil} truy cập nó như sau cho phép người dùng: UserBean = UserBean () user.user_id = "23232332"
Amr Angry

1

Bạn nên xem Thuộc tính được tính

Trong mẫu mã của bạn, perimeterlà một thuộc tính không được sao lưu bởi một biến lớp, thay vào đó giá trị của nó được tính bằng getphương thức và được lưu trữ qua setphương thức - thường được gọi là gettersetter .

Khi bạn sử dụng thuộc tính đó như thế này:

var cp = myClass.perimeter

bạn đang gọi mã chứa trong getkhối mã và khi bạn sử dụng nó như thế này:

myClass.perimeter = 5.0

bạn đang gọi mã có trong setkhối mã, nơi newValueđược tự động điền với giá trị được cung cấp ở bên phải của toán tử gán.

Các thuộc tính được tính toán có thể được ghi đọc nếu cả getter và setter đều được chỉ định hoặc chỉ đọc nếu chỉ getter được chỉ định.


0

biến khai báo và gọi như thế này trong một lớp

class X {
    var x: Int = 3

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

//value of x is:  3

Bây giờ bạn muốn lập trình để giá trị mặc định của x lớn hơn hoặc bằng 3. Bây giờ hãy lấy trường hợp giả thiết nếu x nhỏ hơn 3, chương trình của bạn sẽ bị lỗi. vì vậy, bạn muốn mọi người đặt 3 hoặc nhiều hơn 3. Swift đã giúp bạn dễ dàng và điều quan trọng là phải hiểu cách xác định niên đại của giá trị biến số này vì chúng sẽ được sử dụng rộng rãi trong phát triển iOS. Bây giờ chúng ta hãy xem cách get và set sẽ được sử dụng ở đây.

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

nếu bạn vẫn còn nghi ngờ, chỉ cần nhớ rằng, việc sử dụng get và set là để cập nhật bất kỳ biến nào theo cách chúng ta muốn nó được cập nhật. lấy và đặt sẽ cho phép bạn kiểm soát tốt hơn để quy tắc logic của bạn. Công cụ mạnh mẽ do đó không dễ hiểu.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.