What makes about as much sense as their guideline on (not) using
exceptions... At least the later versions kinda admit that their
guidelines follow being locked in messed up codebases.
How you measure "often"? Or more interestingly why?
"often" is how frequently one runs into a given situation while writing
a piece of code.
issues which show up very frequently, like variable declarations or
expression syntax, may weight more heavily than something seen a little
less often (such as a method declaration), which in turn may weigh more
heavily than a class declaration, ...
the weighting would then also be:
how often is a parent class needed;
how often is more than one parent needed (and would not be easily
achievable via interfaces);
how often are multiple parent classes needed (and not easily achievable
by an object containing instances of "parent" classes, rather than
direct inheritance);
....
the reason for this sort of weighting is more based on the estimated
level of "awkwardness" caused by having a less optimal solution in a
given situation.
if the added awkwardness of missing something is likely to be moderately
small, but the gains from not having to deal with it are greater, it may
make more sense to leave it out.
like, something which is mildly painful, but rare, is less of an issue
than something only slightly annoying, but happening all the time.
if, OTOH, the feature either has little cost, or otherwise justifies its
costs, then it makes more sense to retain it.
granted, yes, this is a little moot for C++, which already has MI.
The base guideline is "do the right thing" or "use the/a right tool".
You make decision on the particular situation. Where MI will or will not
make sense. Entirely unrelated on MI's usefulness in other situations.
IME one completely sensible use of MI is where you mix different
hierarchies. Like an UI framework like MFC and the implementation of
your model and other stuff. A usual bad way is to just use classwizard
and punch in the code wherever it placed //TODO. While it is ways better
to write the logic separately, independent of an UI, and glue them
together -- possibly using trivial templates.
assuming a person couldn't use MI, how much annoyance would this likely
add overall?...
in languages which lack MI, the situations where a person doesn't have
MI but is doing things which "imply" MI, typically end up as a new class
containing instances of the classes it would normally inherit from.
this will typically in-turn add, maybe, a little bit of indirection (or,
maybe, a few getters/setters and/or "glue" classes), but usually this
isn't a big deal (especially if the scenario is relatively infrequent).
for example, in cases where I have written code in Java (or even C#),
there are plenty of other things which are *considerably* more annoying
than its lack of MI.
The reason is probably simpler: authors of those didn't want to mess
with object layout issues. It beats me why disallowing code from
interfaces, not only data... I'm yet to hear a on-FUD argument here.
object layout is a bigger issue for a compiler or a VM, if you have a
feature which adds a big set of ugliness in the compiler, but only
rarely is of much obvious benefit to programmers, does really it make
sense?...
could this effort not have been better spent on other big-ugly features
which provide more obvious / immediate benefits?...
FWIW, in my case, the code for dealing with all of the fun with object
layouts and "efficiently" getting/setting fields and performing method
calls, it actually some of the more complex code in the VM (and I don't
even have "proper" MI). a person may well find that this is the sort of
thing prone to "grow hair" when implemented.
granted, my object and scoping model is admittedly a bit more "advanced"
(IOW: overly complex) than the models used by Java or C# (probably
doesn't help matters).
as well, the tradeoffs of being moderately high-performance,
thread-safe, and supporting dynamically modifiable class and object
layouts, does not make for pretty code (internally, a lot of it is
actually a bunch of jerking around with function-pointers I have come to
term "plumbing pipe logic", partly as the control-flow of the program
works partly like "pipe dream", with the green-liquid being the main
execution path, sometimes with external logic setting up the "pipes",
and sometimes they reconfigure themselves).
actually, a fair chunk of the VM works this way, partly as "simpler"
options, like "if()" conditionals, state-variables, and "switch()"
blocks, tend to be slower and are ideally kept out of the main execution
path (even if it can make some areas of code look a bit evil). ideally,
we want the execution path to head "straight towards the goal" while
minimizing "detours".
simplification is welcome when it can have reasonably good tradeoffs.
MI is more one of those things left for a future time for if/when I can
justify the effort needed to extend the FFI to better support C++
(partly has to do with parsing C++, and partly has to do with
uncertainties related to the various C++ ABIs).
as-is, the goal is mostly just "good interfacing with C", and if C++
code wants to be accessible via the FFI, it has to do so on 'extern "C"'
terms. (there is a lot of "hair" in all this, in terms of even little
things, like how struct passing/returning is handled in the AMD64 ABI, ...).
had to find working links:
http://people.freebsd.org/~obrien/amd64-elf-abi.pdf
http://mentorembedded.github.com/cxx-abi/abi.html
....
yes, a fair amount of the logic for this part is actually written in
assembler...
If you put down a language that aims for just a small subset of possible
problems it is okay to restrict. Certainly if in that realm the dropped
tools are really not needed.
yeah, in my case, this is mostly for a scripting language (and is
more-or-less a variant of ECMAScript).
its most direct use-case is for writing game monster-AI scripts and
similar, but I have also used it some for things like animation control, ...
it is used as a scripting language, but also tries to be "moderately
solid" (or at least, not a total joke) as a general-purpose language as
well (supporting static typing, class/instance OO, ... as well). it
mostly borrows similar syntax to ActionScript3.
regarding language-features, it is "loosely comparable" with C# (though
there feature-sets are not exactly 1:1, so C# has features my language
lacks and likewise).
regarding other language features, it is also more-or-less a C superset
(it includes pretty much the entire C typesystem, most of C's semantics,
and many elements of C syntax as well, and most C code should be fairly
easily portable to analogous code in the scripting language, albeit with
some syntax differences). (it should be an easier porting job than to
Java and C#, partly as the current language semantics align much more
closely).
( I once considered trying to port Quake to my scripting language as a
test, but was hard-pressed to justify the time/effort needed to do so,
as this would still be a big PITA though. )
it is also struct compatible and (with care) function-pointer compatible
with C (this part runs on black magic though).
performance is a bit worse than Java or C#, mostly because it still runs
on an interpreter (based on indirect-threaded-code), rather than a JIT,
and so still runs considerably slower than native.
(as-is, raw performance hasn't been that big of an issue though, as most
"heavy lifting" is still done by C and C++ code...).
it has not really been tested much in "real-world" usage, and would
still need to have many bugs shaken out and problems addressed (given
the types of bugs I still run into periodically, I will make no claim
that it is really).
its main nifty feature is mostly its C FFI, but considering that the C
FFI is itself a pretty big chunk of code, it isn't really a cheap feature.
the FFI actually involves a part that was originally written as a
C-compiler frontend, but it wasn't a very good C compiler (vs just using
MSVC or GCC, it was kind-of slow and very buggy) so it ended up mostly
re-purposed as an FFI tool.
I had considered reviving the C compiler (as a compiler) a few times
(probably using the same VM backend as my scripting language), but this
would itself be a big project.
C++ aimed for the most general arena. And most people admit that when
you need MI you really need it, and the alternatives are pretty crappy.
Implementation-wise it is not such a big burden. More so on user side:
with MI in the mix you can't just keep casting stuff around carelessly.
But who said you should rather aim to support sloppy casting habits?
if the class is a compound object, then a person can pass the relevant
sub-member.
Those cosmic hierarchies in C++ was forced in early times due to lack of
templates (or template-based libraries). Than as that feature (plus
native RTTI) entered you could just cut the obsolete roots and tangles.
I think they were more mostly a problem of many people just thinking
about OO in ways that don't make much sense...
many introductions (and college classes involving) OO, tend to approach
it more as if it were a taxonomy system for approaching objects (and
use, as examples, taxonomies).
a taxonomy system is IMO a poor model to use for a class hierarchy, but
sadly it is apparently the main way many (most?) people tend to
conceptualize hierarchies (well, along with "chain of command" systems,
....).
granted, approaching it more as "I can't clearly say what it is, but it
isn't really a taxonomy" doesn't really help matters much...
many "introductions" show as "examples" things which involve overly deep
nesting in a taxonomy-like manner.
Object/Creature/Animal/Vertebrate/Mammal/Hominid/Human
then people end up designing class hierarchies likewise, with lots of
classes which "don't actually really do anything".
now, try to explain that this is pointless, and all that is really
needed is something like, say:
Entity/ActorBase/Human
say:
Entity: anything which may appear in the scene-graph (defines general
scene-graph entity methods);
ActorBase: an entity which may exhibit AI-controlled behaviors (defines
various AI related methods);
Human: a specific type of entity exhibiting AI-controlled behaviors.
these sorts of differences are subtle, but relevant.
granted, technically, a person could just make Entity and/or ActorBase
be interfaces (and Human as a raw base-class), but in my case I chose to
have them as classes (mostly as there is nothing really more-sensible
for them to inherit from).
(also, Entity may actually inherit from Object, but stating this
explicitly is usually kind-of pointless...).
well, and, my actual classes are more things like:
Entity/ActorBase/monster_soldier
and:
Entity/ActorBase/passive_sheep
and similar (there is no actual "Human" class...).
or such...