However, we observe that given a least common denominator interface, one must implement more complicated interfaces over the basic one. So in reality, although most tools can access most objects (ioctl()s notwithstanding), every tool in fact assumes some higher-level interface, and only makes sense operating on objects that conform to that interface.
Examples include record-per-line files (on which grep operates), record-and-field databases, key-value databases, tree-structured files, rich-structured files (graphics or object file formats), and daemons which expect a readwrite dialog based on a specific protocol.
How do we retain the modularity of a common interface while making higher-level interfaces explicit? We favor designing a system based on method invocation. The least common denominator is that any tool can query the interfaces supported by any object. However, objects can implement multiple interfaces, thereby allowing objects to work with common tools that use simple interfaces, while also offering more specific interfaces to tools which can manipulate them. Because the interfaces are explicitly declared, tools can detect whether they are operating on objects for which they make sense.