The implementation above did not allow multiple definitions with the implicit Post calling one another. Here is a fixed implementation that still uses ambiguity slightly differently with the help of shapeless’s LowPriority:
Generic solution
trait PostConstruction
object PostConstruction {
implicit def ev(implicit lp : shapeless.LowPriority) : PostConstruction = new PostConstruction {}
}
trait HasPostConstructionOnlyMembers {
@scala.annotation.implicitAmbiguous("This is a post-construction definition only!")
final protected implicit def __PostConstruction1(implicit lp : shapeless.LowPriority) : PostConstruction = new PostConstruction {}
final protected implicit def __PostConstruction2(implicit lp : shapeless.LowPriority) : PostConstruction = new PostConstruction {}
}
Library
class DSLClass extends HasPostConstructionOnlyMembers {
private lazy val runOncePostConstruction : Int = 0 //Do something here
protected def post1(implicit p : PostConstruction) : Int = runOncePostConstruction
def post2(implicit p : PostConstruction) : Int = post1
}
User code
new DSLClass{}.post2 //compiles
new DSLClass{post1} //error: This is a post-construction definition only!
new DSLClass{post2} //error: This is a post-construction definition only!