2017-12-18 84 views
5

Tôi đang thiết kế các API của mình để lấy các đối tượng truy vấn cụ thể dưới dạng một tham số duy nhất thay vì phát ra các chữ ký của tất cả các vị trí có thể truyền thông số.Bạn có thể tận dụng các trình khởi tạo mặc định của Swift cho các cấu trúc để đơn giản hóa việc truyền tham số không?

Ví dụ, thay vì viết này ...

func someQuery(requiredA:Bool, requiredB:Int, requiredC:String, defaultedA:Bool = false, defaultedB:Int = 1, defaultedC:String = "X", optionalA:Bool? = nil, optionalB:Int? = nil, optionalC:String? = nil){ 
    .... 
} 

Tôi đang viết này ...

func someQuery(queryParams:QueryParams){ 
    .... 
} 

Và tôi xác định (một phần - hơn dưới đây) truy vấn đối tượng như thế này ...;

struct QueryObject{ 
    let requiredA : Bool 
    let requiredB : Int 
    let requiredC : String 
    let defaultedA : Bool 
    let defaultedB : Int 
    let defaultedC : String 
    let optionalA : Bool? 
    let optionalB : Int? 
    let optionalC : String? 
} 

Vì tôi chắc chắn bạn có thể biết tên, ví dụ này, một số là bắt buộc, một số có mặc định và một số là hoàn toàn tùy chọn.

Bây giờ để xác định đối tượng QueryParams, tôi đang cố gắng tạo ra nó, người dùng chỉ phải xác định các tham số cần thiết, và có thể chỉ định tùy chọn các thông số khác nếu cần/thấy phù hợp.

Đây là những gì tôi là sau khi ...

// At a minimum 
let queryParams = QueryParams(requiredA:true, requiredB:1, requiredC:"x") 

// Minimums overriding a default 
let queryParams = QueryParams(requiredA:true, requiredB:1, requiredC:"x", defaultC:"y") 

// Minimums plus an optional, still picking up all defaults 
let queryParams = QueryParams(requiredA:true, requiredB:1, requiredC:"x", optionalB:8) 

Để đạt được điều này, tôi đã tạo initializer của riêng tôi mà không làm gì nhưng trong nội bộ gán các thông số, như vậy ...

struct QueryParams{ 

    init(
     requiredA : Bool, 
     requiredB : Int, 
     requiredC : String, 
     defaultedA : Bool = true, 
     defaultedB : Int  = 1, 
     defaultedC : String = "x", 
     optionalA : Bool? = nil, 
     optionalB : Int? = nil, 
     optionalC : String? = nil 
    ){ 
     self.requiredA = requiredA 
     self.requiredB = requiredB 
     self.requiredC = requiredC 
     self.defaultedA = defaultedA 
     self.defaultedB = defaultedB 
     self.defaultedC = defaultedC 
     self.optionalA = optionalA 
     self.optionalB = optionalB 
     self.optionalC = optionalC 
    } 

    let requiredA : Bool 
    let requiredB : Int 
    let requiredC : String 
    let defaultedA : Bool 
    let defaultedB : Int 
    let defaultedC : String 
    let optionalA : Bool? 
    let optionalB : Int? 
    let optionalC : String? 
} 

... mà có vẻ như một LOT của mã boilerplate. Tôi đang cố gắng để tìm hiểu xem có cách nào để tận dụng Swift của sáng tạo của một initializer mặc định của struct vì vậy tôi không phải viết tất cả những điều đó bằng tay.

Đáng chú ý:

  1. Tôi chọn cấu trúc ở đây vì Swift mang lại cho họ một initializers mặc định trong khi lớp AFAIK không có được điều đó.
  2. Rõ ràng, các thông số bắt buộc phải đến trước. Khác với điều đó, nó không quan trọng (mặc dù nó là tốt nếu họ có được theo thứ tự định nghĩa quá. Điểm là tôi không quan tâm.)
  3. Các biến thành viên có thể là let hoặc var. Tôi chỉ sử dụng let làm thói quen.

Vì vậy, ... mã này có thể được đơn giản hóa/giảm/loại bỏ không?

+1

Đã chỉnh sửa. Hãy làm tương tự cho những thứ như thế này. Đó là những gì tôi làm. – MarqueIV

Trả lời

0

Bạn không thể nhận loại điều khiển đó từ trình khởi chạy mặc định trên chính nó. Xét về số tiền ít nhất của mã, tôi sẽ giới thiệu một cái gì đó như thế này.

struct QueryParams{ 

    let requiredA : Bool 
    let requiredB : Int 
    let requiredC : String 
    var defaultedA : Bool = true 
    var defaultedB : Int = 1 
    var defaultedC : String = "x" 
    var optionalA : Bool? = nil 
    var optionalB : Int? = nil 
    var optionalC : String? = nil 
} 

extension QueryParams { 
    init(
     requiredA : Bool, 
     requiredB : Int, 
     requiredC : String 
     ){ 
     self.requiredA = requiredA 
     self.requiredB = requiredB 
     self.requiredC = requiredC 
    } 
} 

Bằng cách đặt trình khởi chạy tùy chỉnh của bạn trong tiện ích mở rộng, bạn giữ bộ khởi tạo mặc định miễn phí. Vấn đề duy nhất là nếu họ chỉ muốn tùy chỉnh một số thuộc tính không cần thiết, mà họ sẽ cần phải làm sau khi khởi tạo.

+0

Đúng, nhưng điểm nào là giữ bộ khởi tạo mặc định nếu nó buộc bạn chỉ định mọi thứ? Và nếu bạn phải viết một initializer anyway, sau đó bạn cũng có thể thịt nó ra để xử lý tất cả các trường hợp bằng cách sử dụng mặc định, và nếu bạn làm điều đó, sau đó không cần khởi tạo mặc định anyway.Thêm vào đó, lợi ích khác của bộ khởi tạo đầy đủ là mọi thứ có thể được tạo thành Let. Tôi chỉ hy vọng có một số cách để làm điều này tự động, nhưng tôi bắt đầu nghĩ rằng không có. – MarqueIV

+0

Điểm của bạn hợp lệ. Theo tôi, bạn nên đi với những gì bạn đang làm ngay cả khi nó có vẻ như rất nhiều boilerplate. Đây chỉ là một cách để có được sự linh hoạt nhất với số lượng mã ít nhất dựa trên những gì bạn đang tìm kiếm. Thật không may, những gì bạn đang tìm kiếm chính xác là không có sẵn. Nó quá xấu nó không thể phát hiện giá trị mặc định và điều chỉnh initializer mặc định cho phù hợp. – JustinM

+0

Đồng ý hoàn toàn. Luôn luôn có Swift 5! :) Cảm ơn một lần nữa! – MarqueIV

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