2015-09-30 13 views
11

Tôi đang cố gắng áp dụng một phần mở rộng giao thức hạn chế đến một struct (Swift 2.0) và nhận được lỗi biên dịch sau:phần mở rộng Nghị định thư về Struct nguyên nhân biên dịch lỗi 'Tự' chế để loại phi giao thức

type 'Self' constrained to non-protocol type 'Foo'

struct Foo: MyProtocol { 
    let myVar: String 

    init(myVar: String) { 
     self.myVar = myVar 
    } 
} 

protocol MyProtocol { 
    func bar() 
} 

extension MyProtocol where Self: Foo { 
    func bar() { 
     print(myVar) 
    } 
} 

let foo = Foo(myVar: "Hello, Protocol") 
foo.bar() 

Tôi có thể sửa lỗi này bằng cách thay đổi struct Foo thành class Foo nhưng tôi không hiểu tại sao tính năng này hoạt động. Tại sao tôi không thể làm một giao thức ràng buộc where Self: một cấu trúc?

Trả lời

16

Đây là hành vi mong đợi xem xét struct không có nghĩa là được thừa kế mà ký hiệu là :.

Các cách chính xác để đạt được những gì bạn mô tả sẽ là một cái gì đó như dấu hiệu bình đẳng như:

extension MyProtocol where Self == Foo { 
    func bar() { 
     print(myVar) 
    } 
} 

Nhưng điều này không biên dịch đối với một số lý do ngớ ngẩn như:

Same-type requirement makes generic parameter Self non-generic

Đối với những gì nó có giá trị , bạn có thể đạt được kết quả tương tự như sau:

protocol FooProtocol { 
    var myVar: String { get } 
} 
struct Foo: FooProtocol, MyProtocol { 
    let myVar: String 
} 

protocol MyProtocol {} 
extension MyProtocol where Self: FooProtocol { 
    func bar() { 
    print(myVar) 
    } 
} 

nơi FooProtocol là giả mạo chỉ có Foo nên mở rộng.

Nhiều thư viện của bên thứ ba cố gắng extend loại thư viện chuẩn struct loại (ví dụ: Tùy chọn) sử dụng giải pháp thay thế như trên.

+0

Vâng, đó là gây phiền nhiễu sau đó. Cảm ơn câu trả lời! – Benjohn

3

Tôi cũng đã gặp sự cố này. Mặc dù tôi cũng muốn hiểu rõ hơn về lý do tại sao đây là như vậy, tài liệu tham khảo ngôn ngữ Swift (hướng dẫn không nói gì về điều này) có sau từ phần Generic Tham số:

Where Clauses

You can specify additional requirements on type parameters and their associated types by including a where clause after the generic parameter list. A where clause consists of the where keyword, followed by a comma-separated list of one or more requirements.

The requirements in a where clause specify that a type parameter inherits from a class or conforms to a protocol or protocol composition. Although the where clause provides syntactic sugar for expressing simple constraints on type parameters (for instance, T: Comparable is equivalent to T where T: Comparable and so on), you can use it to provide more complex constraints on type parameters and their associated types. For instance, you can express the constraints that a generic type T inherits from a class C and conforms to a protocol P as <T where T: C, T: P>.

Vì vậy, 'Ngã' không thể là một struct hoặc emum nó có vẻ, đó là một sự xấu hổ. Có lẽ có một lý do thiết kế ngôn ngữ cho việc này. Mặc dù vậy, thông báo lỗi trình biên dịch có thể rõ ràng hơn.

0

Như Foo là một loại tồn tại, bạn chỉ có thể mở rộng nó theo cách này:

struct Foo { // <== remove MyProtocol 
    let myVar: String 

    init(myVar: String) { 
     self.myVar = myVar 
    } 
} 

// extending the type 
extension Foo: MyProtocol { 
    func bar() { 
     print(myVar) 
    } 
} 

Từ The Swift Programming Language (Swift 2.2):

If you define an extension to add new functionality to an existing type, the new functionality will be available on all existing instances of that type, even if they were created before the extension was defined.

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