No, I donβt think itβs possible, because you can only use Self in protocols, because itβs just a placeholder for the type that will conform to this protocol. This is not a real type of type A or B , so you cannot use it when defining classes, as if it were Any or AnyObject .
So, create a protocol that forces the corresponding types to implement the init(finishBlock:) initializer init(finishBlock:) :
protocol BlockInitializable { init(finishBlock: ((_ operation: Self) -> Void)?) } class A: BlockInitializable { init() {} convenience required init(finishBlock: ((_ operation: A) -> Void)?) { self.init() finishBlock?(self) } }
and you will get the following error:
Requirement for the protocol is "Blocked" init (finishBlock :) cannot be satisfied by a non-final class (A) , because it uses the "I" in the position of a non-parametric, non-result.
and the worse you lose the general type of Self operation with parameters.
To fix this, you must mark your class as final or use a struct, which is the final type. However, you will lose the ability to subclass these types. The reason why you should do this and why you cannot use Self in subclasses of types is explained here , so I recommend you take a look at it.
I will go over with the last option and use struct:
protocol Initializable { init() } protocol BlockInitializable: Initializable { init(finishBlock: ((_ operation: Self) -> Void)?) } extension BlockInitializable { init(finishBlock: ((_ operation: Self) -> Void)?) { self.init() finishBlock?(self) } }
then define A and B as struct:
struct A: BlockInitializable { } struct B: BlockInitializable { func fooOnlyInB() { print("Only in B") } }
and you can do the following:
let blockA = A { operation in print("Only in A") } let blockB = B { operation in operation.fooOnlyInB() }
You can download the playground from here .