On Wednesday, November 15, 2017 14:43:33 Dr. Assembly via Digitalmars-d- learn wrote: > I'm learning to use interface with contracts. In below code, in > isn't being "called". Can someone point out why? what am I doing > wrong? > > void main() { > C c = new C(); > writeln(c.foo(1)); > } > > interface I > { > int foo(int i) > in { assert(i > 2); } > out (result) { assert(result != 0); } > > void baa(); > } > > class C : I > { > int foo(int i) { > return i * 2; > } > > void baa() { > writeln("Hello!"); > } > }
Okay. When inheritance gets involved, contracts get a bit special. If you had a free function or a struct's member function, things would be simple enough. The in contract would be run before the function's bode was run, and the out contract would be run afterwards. If either failed, an AssertError would be thrown. However, it works a bit differently with classes. To quote the documentation ( section 23.3: https://dlang.org/spec/contracts.html ): =========== 1. If a function in a derived class overrides a function in its super class, then only one of the in contracts of the function and its base functions must be satisfied. Overriding functions then becomes a process of loosening the in contracts. 2. A function without an in contract means that any values of the function parameters are allowed. This implies that if any function in an inheritance hierarchy has no in contract, then in contracts on functions overriding it have no useful effect. 3. Conversely, all of the out contracts need to be satisfied, so overriding functions becomes a processes of tightening the out contracts. =========== So, effectively, in contracts are all ||ed and out contracts are all &&ed, and the lack of an in contract means that that contract passes. So, if you don't have an in contract, or if you have an empty one, then all base class (or interface) contracts are pointless for that derived function. So, in contracts only really get inherited in the sense that it gives you another contract that could pass. It really doesn't provide a way to restrict derived functions. So, it's pointless to put an in contract on an interface's function unless you're trying to ensure that nothing in derived contracts is any stricter than that contract, which in practice likely means that it's pointless to put an in contract on an interface function. However, out contracts do restrict derived functions, since those are effectively &&ed together. So, it can make sense to put those are interfaces. - Jonathan M Davis