2014-06-22 13 views
6

Tôi vừa xác định một giao thức rất đơn giản và một lớp sử dụng Generics có thể xử lý giao thức này.Giao thức: Không thể gán cho 'X' trong 'Y' trong Swift

Trong dòng được đánh dấu bằng lỗi mà bạn sẽ nhận được lỗi:. "Không thể gán cho 'cờ' trong 'aObj'

protocol Flag { 
    var flag: Bool {get set} 
} 


class TestFlag<T: Flag> { 

    func toggle(aObj: T) { 

     if aObj.flag { 
      aObj.flag = false; // <--- error 
     } else { 
      aObj.flag = true; // <--- error 
     } 
    } 
} 

Bạn có một ý tưởng tại sao và những gì tôi cần phải thay đổi sửa chữa nó

+0

Chỉ cần sao chép nó trong một sân chơi để kiểm tra – Stephan

Trả lời

6

Từ docs:

Function parameters are constants by default. Trying to change the value of a function parameter from within the body of that function results in a compile-time error. This means that you can’t change the value of a parameter by mistake.

Trong trường hợp này, bạn có thể thêm inout để Toggle là pe rsisted ngoài gọi hàm của bạn:

func toggle(inout aObj: T) {   
    if aObj.flag { 
     aObj.flag = false; 
    else { 
     aObj.flag = true; 
    } 
} 

Bạn có thể cũng đã làm:

func toggle(var aObj: T) { 
} 

nhưng điều đó có thể không đạt được những gì bạn muốn.

+2

Tại sao một downvote? – manojlds

+0

Tôi có cùng một vấn đề, nhưng trong trường hợp của tôi, aObj là tài sản của lớp học. Tôi cần làm 'var aObj = self.aObj; aObj.flag = true' –

2

câu trả lời của manojlds là chính xác và do đó tôi chấp nhận nó.

Tuy nhiên, có một câu trả lời tương tự cách đây vài ngày với cùng một giải pháp nhưng với một đối số khác (dường như đã bị xóa).

Luận điểm là về việc người khiếu nại không thể biết giao thức được sử dụng cho một lớp, một cấu trúc hay một enum. Với Swift, các giao thức có thể được áp dụng trên tất cả các kiểu này. Nhưng các cá thể struct sử dụng một cuộc gọi theo giá trị và cho các cá thể lớp (các đối tượng), nó cho chúng ta một cuộc gọi tham chiếu.

Từ quan điểm của tôi câu trả lời này là đúng quá, vì bạn có thể giải quyết vấn đề với một giải pháp thứ 2:

@objc 
protocol Flag { 
    var flag: Bool {get set} 
} 

Chỉ cần thêm attriute @obj trên giao thức. Kết quả là bạn chỉ có thể sử dụng giao thức này cho một lớp dẫn đến kết quả chỉ các cuộc gọi được tham chiếu bằng cách cho phép. Do đó trình biên dịch không cần thông tin inout nữa.

Nhưng tôi đã tìm kiếm giải pháp để tăng khả năng sử dụng lại giao thức và sử dụng đề xuất manojlds.

+4

Bạn cũng có thể làm điều này ... giao thức Cờ: lớp {...} –

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