Không, tôi không nghĩ điều đó là có thể vì bạn chỉ có thể sử dụng Self
trong giao thức vì nó chỉ là trình giữ chỗ cho loại phù hợp với giao thức đó. Nó không phải là một loại thực như A
hoặc B
do đó bạn không thể sử dụng nó khi xác định các lớp như thể nó là Any
hoặc AnyObject
.
Vì vậy, hãy tạo ra một giao thức mà lực lượng phù hợp với các loại để thực hiện init(finishBlock:)
initializer:
protocol BlockInitializable {
init(finishBlock: ((_ operation: Self) -> Void)?)
}
class A: BlockInitializable {
init() {}
convenience required init(finishBlock: ((_ operation: A) -> Void)?) {
self.init()
finishBlock?(self)
}
}
và bạn sẽ nhận được lỗi sau:
Protocol "Blocked" requirement init(finishBlock:) can not be satisifed by a non-final class (A)
because it uses "Self" in a non-parameter, non-result type position.
và những gì tồi tệ hơn bạn sẽ mất các generic nhập Self
của thông số hoạt động.
Để khắc phục điều này, bạn nên đánh dấu lớp của mình là cuối cùng hoặc sử dụng struct là loại cuối cùng. Tuy nhiên, bạn sẽ mất khả năng phân lớp các loại đó. Lý do tại sao bạn phải làm điều đó và lý do tại sao bạn không thể sử dụng Self
trong các loại được phân loại được giải thích here vì vậy tôi khuyên bạn nên xem xét nó.
Tôi sẽ đi với các tùy chọn và sử dụng sau struct:
protocol Initializable {
init()
}
protocol BlockInitializable: Initializable {
init(finishBlock: ((_ operation: Self) -> Void)?)
}
extension BlockInitializable {
init(finishBlock: ((_ operation: Self) -> Void)?) {
self.init()
finishBlock?(self)
}
}
sau đó xác định A
và B
như struct:
struct A: BlockInitializable {
}
struct B: BlockInitializable {
func fooOnlyInB() {
print("Only in B")
}
}
và bạn sẽ có thể làm như sau:
let blockA = A { operation in
print("Only in A")
}
let blockB = B { operation in
operation.fooOnlyInB()
}
Bạn có thể tải xuống sân chơi từ here.
Thú vị! Tôi muốn xem liệu điều này có thể làm việc bằng cách tạo ra một giao thức với một yêu cầu 'Self' trong' init', nhưng tôi đã gặp lỗi được đề cập trong [câu hỏi tương tự này] (http://stackoverflow.com/q/32999293/3769927). – kabiroberai