Tham số tùy chọn mặc định trong hàm Swift


107

Khi tôi đặt firstThingthành mặc định, nilđiều này sẽ hoạt động, nếu không có giá trị mặc định, niltôi sẽ gặp lỗi thiếu tham số khi gọi hàm.

Bằng cách nhập, Int?tôi nghĩ rằng nó làm cho nó trở thành tùy chọn với giá trị mặc định là nil, tôi nói đúng không? Và nếu vậy, tại sao nó không hoạt động mà không có = nil?

func test(firstThing: Int? = nil) {
    if firstThing != nil {
        print(firstThing!)
    }
    print("done")
}
test()

1
Hãy xem xét rằng bạn có thể viết func test(firstThing: Int = 4): một Optionaltham số không có giá trị mặc định. Các Optionalloại (đó là những gì ?trong một cái tên kiểu mở rộng tới) là một loại giá trị; "tham số tùy chọn" là một tên không may cho một tham số có thể có hoặc không có trong một lệnh gọi hàm, bất kể kiểu của nó.
zneak

Bạn đã sử dụng phiên bản Swift nào để kiểm tra mã này? Mã của bạn hoạt động tốt !! Tùy chọn chỉ là một loại và các thông số mặc định hoạt động tốt như với một loại khác trong Swift
Victor Sigler

Câu trả lời:


210

Tùy chọn và tham số mặc định là hai thứ khác nhau.

Một tùy chọn là một biến có thể được nil, đó là nó.

Tham số mặc định sử dụng giá trị mặc định khi bạn bỏ qua tham số đó, giá trị mặc định này được chỉ định như sau:func test(param: Int = 0)

Nếu bạn chỉ định một tham số là tùy chọn, bạn phải cung cấp tham số đó, ngay cả khi giá trị bạn muốn chuyển là nil. Nếu hàm của bạn trông giống như thế này func test(param: Int?), bạn không thể gọi nó như thế này test(). Mặc dù tham số là tùy chọn, nhưng nó không có giá trị mặc định.

Bạn cũng có thể kết hợp hai và có một tham số mà phải mất một tùy chọn nơi nillà giá trị mặc định, như thế này: func test(param: Int? = nil).


27
"Nếu bạn chỉ định một tham số là một tùy chọn, bạn phải cung cấp nó". Tuyệt vời, nhờ Swift
andrewtweber

8
@andrewtweber Sự hài hước của bạn được đánh giá cao, nhưng đối với người mới, tôi nghĩ có thể hữu ích khi làm rõ rằng "Tùy chọn" đề cập đến việc cung cấp một đối tượng hoặc giá trị. Bạn không cần phải làm điều đó, thay vào đó bạn có thể cung cấp nil (đại diện cho sự vắng mặt của một đối tượng hoặc giá trị). Bạn chỉ cần quyết định tùy chọn bạn đang chọn.
JD Sandifer

23

Đối số mặc định cho phép bạn gọi hàm mà không cần truyền đối số. Nếu bạn không truyền đối số, thì đối số mặc định sẽ được cung cấp. Vì vậy, bằng cách sử dụng mã của bạn, cái này ...

test()

... giống hệt như thế này:

test(nil)

Nếu bạn bỏ qua đối số mặc định như thế này ...

func test(firstThing: Int?) {
    if firstThing != nil {
        print(firstThing!)
    }
    print("done")
}

... thì bạn không thể làm điều này nữa ...

test()

Nếu làm vậy, bạn sẽ gặp lỗi "thiếu đối số" mà bạn đã mô tả. Bạn phải chuyển một đối số mọi lúc, ngay cả khi đối số đó chỉ là nil:

test(nil)   // this works

18

Swift không giống các ngôn ngữ như JavaScript, nơi bạn có thể gọi một hàm mà không cần chuyển các tham số và nó vẫn sẽ được gọi. Vì vậy, để gọi một hàm trong Swift, bạn cần gán một giá trị cho các tham số của nó.

Giá trị mặc định cho các tham số cho phép bạn gán một giá trị mà không cần chỉ định nó khi gọi hàm. Đó là lý do tại sao test()hoạt động khi bạn chỉ định một giá trị mặc định trên khai báo của thử nghiệm.

Nếu bạn không bao gồm giá trị mặc định đó, bạn cần cung cấp giá trị trong cuộc gọi: test(nil) .

Ngoài ra, và không liên quan trực tiếp đến câu hỏi này, nhưng có lẽ đáng lưu ý, bạn đang sử dụng cách "C ++" để xử lý các con trỏ có thể là null, để xử lý các tùy chọn nil có thể có trong Swift. Đoạn mã sau an toàn hơn (đặc biệt trong phần mềm đa luồng) và nó cho phép bạn tránh bị buộc phải mở gói tùy chọn:

func test(firstThing: Int? = nil) {
    if let firstThing = firstThing {
        print(firstThing)
    }
    print("done")
}
test()

7

Bạn đang bối rối Optionalvới việc có một mặc định. An Optionalchấp nhận giá trị hoặc nil. Có một mặc định cho phép đối số được bỏ qua khi gọi hàm. Một đối số có thể có giá trị mặc định có hoặc không có Optionalkiểu.

func someFunc(param1: String?,
          param2: String = "default value",
          param3: String? = "also has default value") {
    print("param1 = \(param1)")

    print("param2 = \(param2)")

    print("param3 = \(param3)")
}

Ví dụ về cuộc gọi với đầu ra:

someFunc(param1: nil, param2: "specific value", param3: "also specific value")

param1 = nil
param2 = specific value
param3 = Optional("also specific value")

someFunc(param1: "has a value")

param1 = Optional("has a value")
param2 = default value
param3 = Optional("also has default value")

someFunc(param1: nil, param3: nil)

param1 = nil
param2 = default value
param3 = nil

Tóm lại:

  • Nhập bằng? (ví dụ: Chuỗi?) là một Optionalcó thể là số không hoặc có thể chứa một thể hiện của Loại
  • Đối số có giá trị mặc định có thể bị bỏ qua khỏi lệnh gọi hàm và giá trị mặc định sẽ được sử dụng
  • Nếu cả hai Optionalvà có mặc định, thì nó có thể bị bỏ qua khỏi lệnh gọi hàm HOẶC có thể được đưa vào và có thể được cung cấp với giá trị nil (ví dụ: param1: nil)

tôi có thể thêm tham số mặc định dưới dạng một biến như let hoặc var không? Cảm ơn
Yogesh Patel

@YogeshPatel Không chắc ý bạn.
Chuck Krutsinger

như var myName = "Yogesh". Bây giờ, hàm của tôi giống như 1. func getFilterNames (name: string = myName) {} cách tiếp cận này không hoạt động với tôi. 2. func getFilterNames (name: string = "Yogesh") {} phương pháp này phù hợp với tôi. Nhưng tôi muốn cái đầu tiên, vì vậy bạn có thể vui lòng giúp tôi đạt được điều này. Cảm ơn rất nhiều!
Yogesh Patel

@YogeshPatel Tôi nghĩ những gì bạn có thể muốn là func getFilterNames(name: inout String){ }nó sẽ cho phép bạn sửa đổi tên đã được chuyển vào.
Chuck Krutsinger

Không, thưa ngài. tôi không muốn sửa đổi thông số của mình. tôi chỉ muốn cung cấp giá trị mặc định cho tham số của mình nhưng không giống như "Yogesh" tĩnh. tôi muốn làm như let name = "Yogesh" dynamic func getFilterNames (name: string = name) như thế này. nhận được điều này thưa ông? Cảm ơn!
Yogesh Patel

3

"Tham số tùy chọn" có nghĩa là "loại tham số này là tùy chọn". Nó không có nghĩa là "Tham số này là tùy chọn và do đó, có thể bị bỏ qua khi bạn gọi hàm".

Thuật ngữ "tham số tùy chọn" dường như gây nhầm lẫn. Để làm rõ, chính xác hơn là nói "tham số kiểu tùy chọn" thay vì "tham số tùy chọn" vì từ "tùy chọn" ở đây chỉ có nghĩa là để mô tả loại giá trị tham số và không có gì khác.


3

trong trường hợp bạn cần sử dụng tham số bool, bạn chỉ cần gán giá trị mặc định.

func test(WithFlag flag: Bool = false){.....}

thì bạn có thể sử dụng mà không có hoặc với tham số:

test() //here flag automatically has the default value: false
test(WithFlag: true) //here flag has the value: true

Đối với những người không tán thành điều này, thay vào đó bạn có thể sửa lỗi sai để những người khác sẽ hiểu.
Niib Fouda 17/09/18

0

Nếu bạn muốn có thể gọi funccó hoặc không có tham số, bạn có thể tạo một thứ hai funccùng tên gọi tên kia.

func test(firstThing: Int?) {
    if firstThing != nil {
        print(firstThing!)
    }
    print("done")
}

func test() {
    test(firstThing: nil)
}

bây giờ bạn có thể gọi một hàm có tên testmà không có hoặc không có tham số.

// both work
test()
test(firstThing: 5)

Tại sao bạn lại xác định một hàm bổ sung khi bạn chỉ có thể chỉ định nil làm giá trị mặc định cho tham số?
Peter Schorn

-1

Sẽ hơi phức tạp khi bạn cố gắng kết hợp tham số tùy chọn và giá trị mặc định cho tham số đó. Như thế này,

func test(param: Int? = nil)

Hai ý kiến ​​này hoàn toàn trái ngược nhau. Khi bạn có tham số kiểu tùy chọn nhưng bạn cũng cung cấp giá trị mặc định cho nó, thì giờ đây nó không còn là kiểu tùy chọn nữa vì nó có giá trị mặc định. Ngay cả khi giá trị mặc định là nil, swift chỉ cần loại bỏ ràng buộc tùy chọn mà không cần kiểm tra giá trị mặc định là gì.

Vì vậy, tốt hơn là không nên sử dụng nil làm giá trị mặc định.


1
Điều này là không đúng. Không có gì sai khi một tùy chọn có giá trị mặc định (thậm chí nil).
Brian Kendig

những gì tôi đang nói là một khi một biến có giá trị mặc định, nó không phải là tùy chọn theo nghĩa nó sẽ luôn có giá trị.
Shubham Naik

1
Điều đó không đúng, và tôi không chắc bạn đang muốn mô tả điều gì. Tôi nghĩ rằng bạn đang nói một cách chính xác rằng một khi một biến có giá trị được gán cho nó, nó sẽ luôn được gán; bạn không thể bỏ gán nó (cũng như bạn muốn) trừ khi bạn phân bổ nó. Và Swift sẽ cung cấp cho bạn một lỗi biên dịch nếu bạn cố gắng sử dụng một biến trước khi nó có giá trị (như trong var foo: String; print(foo)). Nhưng một đối số hàm có giá trị mặc định là một đối số tùy chọn (bạn không phải chuyển nó trong lệnh gọi hàm) và nó cũng có thể thuộc loại Tùy chọn (cho phép nilgán cho nó, ngay cả khi làm giá trị mặc định).
Brian Kendig

Một tùy chọn về cơ bản là một kiểu kết hợp của <Loại | Nil>, tức là nó có thể có kiểu Specified hoặc kiểu Nil. (Giả sử rằng swift có các Liên minh thì không, nhưng chúng ta đang nói về khái niệm ở đây). vậy Int? = nil là hoàn toàn tốt.
Shayne

-1

Giá trị mặc định không có nghĩa là giá trị mặc định của kiểu dữ liệu. Ở đây giá trị mặc định có nghĩa là giá trị được xác định tại thời điểm xác định hàm. chúng ta phải khai báo giá trị mặc định của biến trong khi xác định biến trong hàm.

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.