2015-05-30 41 views
25

Tôi biết về ký hiệu và hoạt động bit nhưng đôi khi tôi thấy nó ở trước tên biến. Điều gì đặt một số & trước biến làm gì?Dấu và (&) có nghĩa là gì trong ngôn ngữ Swift?

+0

Kiểm tra * In-Out thông số * trong [tài liệu Chức năng Swift] (https://developer.apple.com/library/ios/documentation/Swift/Conceptual/Swift_Programming_Language/Functions.html) – LopSae

Trả lời

34

Nó hoạt động như một inout để làm cho biến một tham số trong phòng. Trong-ra có nghĩa là trong thực tế đi qua giá trị bằng cách tham khảo, không phải theo giá trị. Và nó đòi hỏi không chỉ để chấp nhận giá trị bằng cách tham khảo, bởi cũng để vượt qua nó bằng cách tham khảo, vì vậy vượt qua nó với & - foo(&myVar) thay vì chỉ foo(myVar)

Như bạn thấy bạn có thể sử dụng trong giao lỗi trong Swift, nơi bạn có để tạo tham chiếu lỗi và chuyển nó tới hàm bằng cách sử dụng & hàm sẽ điền giá trị lỗi nếu xảy ra lỗi hoặc chuyển biến trở lại như trước đây

Tại sao chúng ta sử dụng nó? Đôi khi một hàm đã trả về các giá trị khác và chỉ trả về một giá trị khác (giống như một lỗi) sẽ gây nhầm lẫn, vì vậy chúng ta chuyển nó thành một inout. Lần khác, chúng tôi muốn các giá trị được điền bởi hàm do đó chúng tôi không phải lặp qua nhiều giá trị trả về vì hàm đã thực hiện cho chúng tôi - trong số các cách sử dụng khác có thể.

Tôi hy vọng sẽ giúp bạn!

+0

giải thích tuyệt vời cho việc sử dụng &! cảm ơn bạn. – seoyoochan

+7

Nó cũng có thể được sử dụng để gọi API C từ Swift với ý nghĩa C truyền thống của "địa chỉ của" một biến. Trong Swift, nó có dạng UnsafePointer . Vì vậy, ví dụ trong Swift API C mong đợi một con trỏ có thể lấy một tham số của UnsafePointer và bạn có thể gọi nó bằng & myCGFloat. (https://developer.apple.com/library/ios/documentation/Swift/Conceptual/BuildingCocoaApps/InteractingWithCAPIs.html) –

+0

Tôi không hiểu tại sao nó cần thiết vì chữ ký thư đã chỉ định rằng nó là inout. Tại sao lại làm hai lần? – Alper

8

Điều đó có nghĩa rằng đó là biến trong-ra. Bạn có thể làm điều gì đó trực tiếp với biến đó. Nó được thông qua bởi địa chỉ, không phải là một bản sao.

Ví dụ:

var temp = 10 
func add(inout a: Int){ 
    a++ 
} 
add(&temp) 
temp // 11 
+0

và những gì tình hình thay thế ví dụ của bạn? Tôi có nghĩa là nếu bạn đã thực hiện thêm (tạm thời) những gì * làm thế nào * nó sẽ khác nhau? temp sẽ là '10'? – Honey

+0

++ không dùng nữa O :-) –

7

Nếu bạn đặt & trước một biến trong hàm, điều đó có nghĩa biến này là inout biến.

@Icaro đã mô tả ý nghĩa của nó, tôi sẽ chỉ đưa ra một ví dụ để minh họa cho sự khác biệt giữa các biến inout và trong các biến:

func majec(inout xValue:Int, var yValue:Int) { 
    xValue = 100 
    yValue = 200 
} 

var xValue = 33 
var yValue = 33 
majec(&xValue, yValue: yValue) 
xValue //100 
yValue //33 
3

Như đã đề cập trong câu trả lời khác, bạn sử dụng tiền tố & để vượt qua một giá trị tham số inout của một phương thức hoặc cuộc gọi chức năng, như được ghi lại trong Functions > Function Argument Labels and Parameter Names > In-Out Parameters trong Ngôn ngữ lập trình Swift. Nhưng có nhiều hơn thế.

Bạn có thể, trong thực tế, hãy suy nghĩ về các thông số Swift inout và truyền các giá trị cho chúng như tương tự với địa chỉ truyền qua C hoặc C++ hoặc thông qua tham chiếu. Trong thực tế, trình biên dịch sẽ tối ưu hóa việc sử dụng nhiều tham số inout xuống gần bằng cùng một cơ chế (đặc biệt là khi bạn đang gọi các API C hoặc ObjC được nhập khẩu xử lý con trỏ). Tuy nhiên, đó chỉ là tối ưu hóa - ở cấp độ ngữ nghĩa, inout thực sự không truyền địa chỉ xung quanh, điều này giải phóng trình biên dịch để làm cho ngôn ngữ này xây dựng linh hoạt và mạnh mẽ hơn.

Ví dụ, đây là một cấu trúc có sử dụng một chiến lược chung cho việc chứng thực quyền truy cập vào một trong những thuộc tính của nó:

struct Point { 
    private var _x: Int 
    var x: Int { 
     get { 
      print("get x: \(_x)") 
      return _x 
     } 
     set { 
      print("set x: \(newValue)") 
      _x = newValue 
     } 
    } 
    // ... same for y ... 
    init(x: Int, y: Int) { self._x = x; self._y = y } 
} 

(Trong mã "thực", các phương thức getter và setter cho x có thể làm những việc như thực thi tối thiểu Hoặc x có thể thực hiện các thủ thuật thuộc tính được tính toán khác, như nói chuyện với một cơ sở dữ liệu SQL dưới mui xe, ở đây chúng ta chỉ thực hiện cuộc gọi và nhận/thiết lập thuộc tính riêng bên dưới.)

Bây giờ, điều gì xảy ra khi chúng tôi vượt qua x đến thông số inout?

func plusOne(num: inout Int) { 
    num += 1 
} 

var pt = Point(x: 0, y: 1) 
plusOne(num: &pt.x) 
// prints: 
// get x: 0 
// set x: 1 

Vì vậy, mặc dù x là một tài sản tính, đi qua nó "bằng cách tham khảo" sử dụng một tham số inout hoạt động giống như bạn mong muốn nó để nếu x là một tài sản được lưu trữ hoặc một biến địa phương.


Điều này có nghĩa là bạn có thể chuyển tất cả mọi thứ "theo tham chiếu" mà bạn thậm chí không thể xem xét trong C/C++/ObjC. Ví dụ, hãy xem xét các tiêu chuẩn thư viện swap chức năng, mà có bất kỳ hai ... "những điều" và chuyển giá trị của họ:

var a = 1, b = 2 
swap(&a, &b) 
print(a, b) // -> 2 1 

var dict = [ "Malcolm": "Captain", "Kaylee": "Mechanic" ] 
swap(&dict["Malcolm"], &dict["Kaylee"]) 
print(dict) // -> ["Kaylee": "Captain", "Malcolm": "Mechanic"], fanfic ahoy 

let window1 = NSWindow() 
let window2 = NSWindow() 
window1.title = "window 1" 
window2.title = "window 2" 
var windows = [window1, window2] 
swap(&windows[0], &windows[1]) 
print(windows.map { $0.title }) // -> ["window 2", "window 1"] 

Các cách inout công trình cũng cho phép bạn làm những thứ vui vẻ như sử dụng các nhà điều hành += trên lồng nhau gọi chuỗi:

window.frame.origin.x += 10 

... đó là đơn giản hơn rất nhiều so với toàn bộ quá trình phân huỷ một CGRect chỉ để xây dựng một cái mới với một khác nhau x phối hợp.


Đây là phiên bản nhiều sắc thái của inout hành vi, được gọi là "cuộc gọi bằng cách kết quả giá trị", và cách nó có thể tối ưu hóa xuống C-phong cách "đi ngang qua địa chỉ" hành vi, được bảo vệ dưới Declarations > Functions > In-Out Parameters trong Swift Ngôn ngữ lập trình.

+0

Wow, cảm ơn bạn vì lời giải thích cực kỳ toàn diện và khai sáng! Tôi đã không nhận thức được những hành vi tinh tế của các nhà điều hành ký hiệu và nhanh chóng. –

+0

Vấn đề lớn nhất của tôi khi nói về 'inout' là nó khiến tôi muốn đi xuống phố để tăng gấp đôi và uống sữa. – rickster

Các vấn đề liên quan