2015-06-25 18 views
6

Khi đọc tài liệu của Swift, Apple thường sử dụng functionName(_:name:) hoặc một cái gì đó tương tự. Chính xác thì mẫu này đôi khi là _:_:, đôi khi chỉ là _:_:name:. Tôi nghĩ rằng nó đã làm với tốc ký tham số, nhưng tôi không chắc chắn, và không thể tìm thấy lời giải thích trong hướng dẫn lập trình của Swift. Cảm ơn bạn!_: _: và các kết hợp tương tự của dấu hai chấm và dấu gạch dưới nghĩa là gì trong Swift?

Ví dụ:

insert(_:atIndex:) 

Trả lời

8

Dấu gạch dưới cho biết không có tên thông số bên ngoài cho hàm. Apple's Swift Documentation nói về khái niệm này khi bạn viết các chức năng của riêng mình.

Lấy trường hợp bạn viết hàm này (từ tài liệu):

func sayHello(to person: String, and anotherPerson: String) -> String { ... } 

Nếu bạn đã sử dụng chức năng bạn sẽ viết như sau:

sayHello(to: "Bill", and: "Ted") 

Chữ ký này sẽ là sayHello(to:and:). Tuy nhiên, điều gì sẽ xảy ra nếu chúng ta muốn sử dụng hàm này làm sayHello("Bill", "Ted")? Làm cách nào chúng tôi cho biết rằng chúng tôi không muốn có tên thông số bên ngoài? Vâng, đó là nơi gạch dưới xuất hiện. Chúng tôi có thể viết lại hàm như sau:

func sayHello(person: String, _ anotherPerson: String) -> String { ... } 

Lưu ý tham số đầu tiên không cần _, nhưng thông số tiếp theo sẽ không cần. Đầu tiên được suy ra để không có tên tham số. Điều này làm cho chữ ký phương thức cho cuộc gọi này sayHello(_:_:) vì bạn là người gọi không có thông số được đặt tên.

Cập nhật Swift 3.0:

Swift 3.0 xử lý tất cả các thông số như nhau. Tham số đầu tiên hiện yêu cầu dấu gạch dưới để biểu thị sự vắng mặt của tên thông số bên ngoài. Trong ví dụ trên của việc có sayHello("Bill", "Ted") tại địa điểm cuộc gọi, chức năng tương ứng của bạn hoặc phương pháp kê khai sẽ phải

func sayHello(_ person: String, _ anotherPerson: String) -> String { ... } 

Lưu ý việc bổ sung các dấu gạch dưới trước tên tham số nội bộ 'người'.

+1

Câu trả lời hay! Cảm ơn! – rb612

+0

Định nghĩa cuối cùng của bạn khác với 'func sayHello (người: String, anotherPerson: String) -> String {...}'? – 7stud

+0

@ 7stud Kể từ Swift 1.2, nó phụ thuộc nếu bạn đang thực hiện một hàm hoặc một phương thức. Nếu bạn tạo một hàm độc lập, nó không khác gì. Tuy nhiên, nếu bạn khai báo bên trong một lớp (làm cho nó trở thành một phương thức), nó sẽ cho rằng tham số thứ hai (và các tham số tiếp theo) chỉ với tên nội bộ cũng đóng vai trò là tên bên ngoài. Về cơ bản, nếu 'func sayHello (person: String, anotherPerson: String) -> String' được viết dưới dạng hàm, nó sẽ trở thành' sayHello (_: _ :) '. Trong một lớp như một phương thức, nó trở thành 'sayHello (_: anotherPerson:)'. Tôi nghĩ Swift 2 đã thay đổi điều này. –

0

chia sẻ trải nghiệm học tập của tôi.

//MARK: Default 
func join1(s1: String, s2: String, joiner: String) -> String { 
    println("join1" + s1 + joiner + s2) 
    return s1 + joiner + s2 
} 

//MARK: External Parameter Names 
// To make the purpose of these String values clearer, define external parameter names for each join function parameter 
func join2(string s1: String, toString s2: String, withJoiner joiner: String) -> String { 
    println("join2" + s1 + joiner + s2) 
    return s1 + joiner + s2 
} 

//MARK: External Names for Parameters with Default Values 
func join3(string s1: String, toString s2: String, withJoiner joiner: String = " ") -> String { 
    println("join3" + s1 + joiner + s2) 
    return s1 + joiner + s2 
} 

//MARK: No External Names for Parameters with Default Values 
func join4(s1: String, s2: String, joiner: String = " ") -> String { 
    println("join4" + s1 + joiner + s2) 
    return s1 + joiner + s2 
} 

//MARK: instead of an explicit external name 
// You can opt out of this behavior by writing an underscore (_) instead of an explicit external name when you define the parameter. However, external names for parameters with default values are preferred. 

func join5(s1: String, _ s2: String, _ joiner: String = " ") -> String { 
    println("join5" + s1 + joiner + s2) 
    return s1 + joiner + s2 
} 

//MARK: Shorthand External Parameter Names 
// Provide an external parameter name with the same local parameter name 
// Swift provides an automatic external name for any parameter that has a default value. The automatic external name is the same as the local name, as if you had written a hash symbol before the local name in your code. 

func join6(#s1: String, s2: String, joiner: String = " ") -> String { 
    println("join6" + s1 + joiner + s2) 
    return s1 + joiner + s2 
} 

Và bạn có thể xem làm thế nào để sử dụng chúng

join1("s1", s2: "s2", joiner: "-") 

join2(string: "s1", toString: "s2", withJoiner: "-") 

join3(string: "s1", toString: "s2", withJoiner: "-") 
join3(string: "s1", toString: "s2") 

join4("s1", s2: "s2", joiner: "-") 
join4("s1", s2: "s2") 

join5("s1", "s2", "-") 
join5("s1", "s2") 

join6(s1: "s1", s2: "s2", joiner: "-") 
join6(s1: "s1", s2: "s2") 
-1

Từ Swift docs:

thông số chức năng có thể có cả tên địa phương (để sử dụng trong cơ thể chức năng của) và tên bên ngoài (để sử dụng khi gọi hàm ), như được mô tả trong Tên tham số ngoài. Điều này cũng đúng với các thông số phương pháp vì các phương thức chỉ là các hàm được kết hợp với một loại. Tuy nhiên, hành vi mặc định của tên địa phương và tên bên ngoài khác nhau đối với các hàm và phương thức.
...
...

Cụ thể, Swift [làm cho] tên tham số đầu tiên trong một phương pháp một tên tham số địa phương theo mặc định, và [làm cho] các tên tham số thứ hai và sau đó cả hai địa phương và tên tham số bên ngoài theo mặc định. Quy ước này phù hợp với quy ước đặt tên và gọi thông thường, sẽ quen thuộc với việc viết các phương pháp Mục tiêu-C và thực hiện các cuộc gọi phương thức biểu cảm mà không cần phải đủ điều kiện tham số của bạn tên.

xem xét phiên bản thay thế này của lớp Counter ...

class Counter { 
    var count: Int = 0 
    func incrementBy(amount: Int, numberOfTimes: Int) { 
     count += amount * numberOfTimes 
    } 
} 

này incrementBy (_: numberOfTimes :) phương pháp có hai tham số-lượng và numberOfTimes. Theo mặc định, Swift xử lý số tiền dưới dạng tên địa phương chỉ , nhưng xử lý numberOfTimes dưới dạng cả tên địa phương và tên bên ngoài. Bạn gọi phương thức như sau:

let counter = Counter() 
counter.incrementBy(5, numberOfTimes: 3) 
// counter value is now 15 

Bạn không cần phải xác định một tên tham số bên ngoài cho giá trị số đầu tiên, bởi vì mục đích của nó là rõ ràng từ tên hàm incrementBy. Đối số thứ hai, tuy nhiên, có đủ điều kiện bởi một tên tham số bên ngoài để làm cho mục đích của nó rõ ràng khi phương pháp được gọi.

hành vi mặc định này có hiệu quả xử lý các phương pháp như nếu bạn đã viết một biểu tượng thăng (#) trước khi tham số numberOfTimes:

func incrementBy(amount: Int, #numberOfTimes: Int) { 
    count += amount * numberOfTimes 
} 

Hành vi mặc định mô tả ở trên có nghĩa là định nghĩa phương pháp trong Swift được viết với cùng một kiểu ngữ pháp như Objective-C, và được gọi theo cách tự nhiên, biểu cảm.

Vì vậy, để vô hiệu hóa những tên bên ngoài của tham số thứ hai của một phương pháp bạn một cách rõ ràng có thể viết '_' cho tên bên ngoài:

class Counter { 
    var count: Int = 0 
    func incrementBy(amount: Int, _ numberOfTimes: Int) { 
     count += amount * numberOfTimes 
    } 
} 

Bây giờ cú pháp cho tên phương pháp trở thành:

incrementBy (__: __ :)

Cú pháp cho bạn biết cách gọi phương thức. Trong trường hợp này, cú pháp cho bạn biết rằng có hai đối số phương pháp un-tên, vì vậy bạn gọi phương thức như thế này:

incrementBy(3, 2) 

Nếu tên phương pháp là incrementBy(_:numberOfTimes:), cú pháp cho bạn biết rằng đối số đầu tiên là un tên trong khi tên của đối số thứ hai là numberOfTimes, vì vậy bạn gọi phương thức như sau:

incrementBy(3, numberOfTimes:2) 
Các vấn đề liên quan