I think you are asking how a contract system can work without OOP and inheritance? As a Racket user who is not familiar with Eiffel, I wonder why the contract system will have anything to do with OOP and inheritance. :)
At a practical level, I think of Racket contracts as a way to get some of the benefits of static type declarations, while maintaining the flexibility of dynamically typed languages. Plus, contracts go beyond just types and can act as assertions.
For example, I can say that a function requires one argument, which is an exact integer ... but also say that it must be an exact positive integer or a union of certain specific values or practically any arbitrarily complex test of the passed value. Thus, contracts in Racket combine what you can do with declarations of type (a) and (b) statements, for example, in C / C ++.
One of them with contracts at Racket is that they can be slow. One way to deal with this is to first use them in development, and then remove them selectively, especially from the "internal loops" of function types. Another approach I tried is to enable or disable wholesale: create a couple of modules, such as contract-on.rkt and contract-off.rkt, where the latter provides macros with nothing to do. Your modules require a .rkt contract, which provides all of any -on or -off files. This is similar to compiling in DEBUG vs RELEASE mode.
If you are coming from Eiffel, maybe my C / C ++ tilt of the Racket will not be useful, but I would like to share it anyway.
Greg Hendershott
source share