Когда я переопределяю функции в D с помощью «внутренних» контрактов, проверяются унаследованные «внутренние» контракты. Если они терпят неудачу, то проверяются переопределенные «входящие» контракты. Если я ничего не указываю в контракте, то это интерпретируется как наличие пустого контракта «в». Таким образом, следующий код успешно компилируется и запускается.
module main;
import std.stdio;
interface I
{
void write( int i )
in
{
assert( i > 0 );
}
}
class C : I
{
void write( int i )
{
writeln( i );
}
}
int main()
{
I i = new C;
i.write( -5 );
getchar();
return 0;
}
Я хочу только, чтобы предварительное условие I.write()
проверялось, когда я вызываю i.write()
, так как это то, что статически известно, что этого достаточно для того, чтобы I.write()
работал компилятором правильно. Проверка всех предварительных условий после динамической диспетчеризации кажется мне странной с точки зрения объектно-ориентированного программирования, поскольку инкапсуляция теряется.
Я мог бы повторить предварительное условие или написать in { assert( false ); }
во всех классах, реализующих интерфейс, но это больно. Является ли это ошибкой дизайна языка D? Или есть какой-то правильный масштабируемый способ сделать это?