proj-oot-old-150618-ootOop

functions of OOP:

clearly, these can be untangled (whether they should be is another question; in Oot we are at least untangling typing from inheritance via everything-is-an-interface)

--

interfaces vs subtypes:

interfaces are transitive/chainable. e.g. if we have a [Int], that is, a list of things that each expose the Int interface, then because we have adapters for Int->Num, Num->Ord, [Ord]->Sort, that list automatically exposes the Sort interface. There is no need to explicitly convert or cast anything.

it is possible to mark an interface as not implicitly chained, however. E.g. each function can be associated with its Godel number integer encoding, but if you have a function and you add 1 to it, you probably should get a compiler error rather than it changing to whatever function has the next Godel number. So the Godel number interface for functions would be marked as manually chained.

now what are OOP classes? they are what i have been calling 'implementations'. That is, they encapsulate/know about the way that the data is represented, in some way that at least in principal there could be more than one of them for the same interface. For example, let's say you have an object representing 8 bytes of data. It exposes an interface like this: read(byte): value, write(byte, value), where 'byte' is an int between 0 and 7 inclusive, and 'value' is an int between 0 and 255 inclusive. Now, you want this to expose an Int64 interface. But there's actually many two ways to do it, for example: big endian and little endian.

so what is subclassing good for and how is it different from interface chaining? Let's say you have a superclass like 'little endian unsigned Int64' which has a fixed-length array of 8 bytes (8 uint8s) internally, and externally exposes the uint64 interface, and, hence, the LimitedPrecisionSuccessorNaturalNumber? interface. You already have arithmetic defined on this because arithmetic is defined using pattern matching on SuccessorNaturalNumber?. But you want to write optimized arithmetic routines that use the byte array. If there were no subclassing you'd only have access to the uint64 interface, which means that only the original implementor could write optimized methods that know about the internal representation.

TODO

method names that start with __ (two underscores) are protected. These are only accessible by the current module, descendent modules, or sibling modules, and only within subimplementations (except that debugging (/profiling/logging) functions, or any function, can access them via the metainfo).

method names that don't start with __ are public. They are accessible by anyone. They are part of the interface implicitly defined by this implementation.

TODO

What about subclassing? I can imagine that you might want to define arithmetic on the Int64 defined above, calculated in an optimized manner that makes use of knowledge about the internal storage format; even though in theory you could define it all in recursive definitions using only zero and successor pattern matching, which can be implemented based on just the standard Int64 interface. Again, these optimized arithmetic ops (not the successor-based ones) will need to know about whether the internal storage is big endian or little endian.

So you have a superclass like 'little endian Int64' and a subclass 'little endian Int64 with arithmetic'. First note that these are what i've been calling 'implementations'. Second, one might just consider the subclass's OOP relation to its super as one defined just by inheritance; it presents a new interface (arithmetic) but that can be done without OOP. What i mean by "defined just by inheritance" is that one could consider the subclass to be a totally separate class than the super, but the inheritance is a synctactic shortcut to copy a bunch of code. However, this is missing something; if you have a 'little endian Int64 with arithmetic', and you have a function that wants a 'little endian Int64' (e.g. this function must be another implementation-dependent optimization), then you can pass the 'little endian Int64 with arithmetic' right in; you don't have to convert it, or to make the function go thru a public interface.

So in addition, subclassing adds some extensibleness/modularity to the process of writing optimized code for interacting with an object's internals.

Note that not allowing a function in another module to demand a 'little endian Int64' means that only functions in the original defining module can contribute efficient implementations of data operations (only composition is allowed, not inheritance). But allowing this goes against my doctrine of 'everything is an interface' and clears the way for ByteString?-demanding parser libraries to spring up. How to fight this?

Note that this business of having subclasses in addition to interfaces because subclasses are allowed to know about the internal data representation is like protected methods and fields.

this ties into the philosophy in that if the class is the aquinas 'essence', that's like saying the internal data format is like kant's 'thing-in-itself'.

and as usual, the reason that multiple inheritance may be confusing is that the two parent classes may use the same name for some protected field or method, which may or may not be desirable.

hmm.. to solve the multiple inheritance problem, the compiler could simply check for overlapping names, and require the inheriting programmer to specify, for each one separately, whether it is to be overlapping (accept this into the namespace even though others are also using the name) or disjoint (rename all occurences of the name in the inheriting superclass; like a hygenic macro)

also, to prevent a culture of overly diverging from everything-is-an-interface, could do: (a) every subclass method is either protected or an implementation of a public interface method (b) if you don't at least mention at least one protected method (remember fields are properties so are the same sort of thing as methods in oot) in your subclass, then it can't be a subclass method, it must be an interface method, (c) only methods attached to an object can be part of the subclass.

---

oot oop design todos

oop vs modules: Objects vs modules as units of reuse?