August 29, 2013
On 16/08/13 23:21, JS wrote:
> You can't get them both at the same time though, which you might just make _A
> final.
>
> The whole point of inheritance is to treat derived classes as if they were base
> classes.

Sorry for delayed response here, I've been fairly heavily focused on other things. :-(

I think it's best if I describe explicitly the code situation I have.  I wasn't trying to be coy before, but just assumed that the pattern I described would either be completely typical or not at all useful -- so I thought a simple example would be better.  (I was also away from the computer when writing several replies, short examples are nicer to write on a phone:-)

The _real_ code is my graph library.  The basic graph type is currently implemented as a final class:
https://github.com/WebDrake/Dgraph/blob/master/dgraph/graph.d#L30-L343

However, this has some speed issues, so I have a fork where that class is extended in several ways:
https://github.com/WebDrake/Dgraph/blob/cache/dgraph/graph.d#L30-L504

The extension is fairly simple.  The class gains a few extra internal data types which cache various calculated values; a couple of functions gain some extra lines to appropriately take care of that extra data; and a couple of other functions are substantially rewritten, to take advantage of that extra data being available.

Now, I'd assumed that this would be a cause where making the one a derivative of the other would make sense, but after discussion here, I'm not so sure that's appropriate (as per Dicebot's remark, "inheritance should not be used as code reusage tool").

> e.g., code was designed to use class _A, you come along, extend _A to A, but
> "trick" to the code to use your A(even though it thinks it's an _A).

That's _not_ the case here, there's no intention of trying to have runtime generics through base interfaces.  I'm trying to do something closer to how RNGs are implemented in Phobos, with many different implementations sharing a common public API.

> To do oop you have to have derivation from base classes, but final stops that.
> Hence your two goals(being able to use oop and being able not to(using final)
> are mutually exclusive).

I'm not trying to "do OOP" per se, in the sense that I'm not trying to create a hierarchy of more general to more specific along the lines of Shape => Rectangle => Square, etc.  But in this case inheritance seems to make sense.

The choice of classes in the first place wasn't because of their inheritance properties, but because the nature of the internal data means the Graph is pretty much unavoidably a reference type, and it's the simplest way to enforce that.

> The only way it can be useful is if the compiler can determine if an object is
> final at compile time... but if it can do this then it doesn't need to be final
> in the first place(it will still be able to inline methods).

Oddly enough, when doing a couple of speed tests with and without the "final" in place, sometimes LDC seemed to be able to optimize better without it there. Though it might be a fluke.
1 2
Next ›   Last »