On Saturday, 25 July 2015 at 10:12:15 UTC, Jonathan M Davis wrote:
On Saturday, 25 July 2015 at 09:44:30 UTC, Jacob Carlborg wrote:
On 2015-07-24 21:04, Walter Bright wrote:
Dynamic cast is no different from QueryInterface(), which is
how it's
done, and the reason is the point of all this - avoiding
needing to
enumerate every interface needed by the leaves at the root of
the call
tree.
I'm not familiar with QueryInterface():
It's part of COM. Basically, it's equivalent to doing something
like
auto f = cast(MyInterface)myObj;
if(f is null)
{ /+ you can't convert it to MyInterface +/ }
else
{ /+ you _can_ convert it +/ }
except that with the way that QueryInterface works, it's
actually possible to get a completely different object out of
it. It doesn't have to have any relation to the original
object, and the new type doesn't have to be in an inheritance
hierarchy with the original type. So, you can do wacky stuff
like have an interface which relates to one object hierarchy
and convert it to an interface from a completely unrelated
object hierarchy just so long as the underlying type knows how
to give you the type you're asking for (be it because it
implements both interfaces or because it's designed to give you
an object that implements the interface you're asking for).
So, QueryInterface isn't actually guaranteed to do anything
like a cast at all. It just guarantees that you'll either get
an object of the type you ask for - somehow - or that the call
will fail.
And the way it's used often seems to be the equivalent of
something like
interface A {}
interface A : B {}
interface Foo {}
interface Bar : Foo {}
class MyClass : B, Bar {}
Foo f = getFoo(); // returns what it is actually a MyClass
A a = cast(A)f;
It happens to work, because the underlying type implements
both, but why on earth would you expect that a Foo would be
related to an A when they're completely unrelated? And yet that
seems to be the sort of thing that gets done with
QueryInterface - at least in the code that I've worked with
that does COM.
Personally, I think that it's nuts to even be attempting to
cast from one interface to an entirely unrelated one and expect
it to work - or to write code in a way that that's a normal way
to do things.
- Jonathan M Davis
It makes sense when one thinks about pure interfaces and
component oriented programming, as preached by one of the
Component Pascal guys. Or for that matter how Go uses interfaces.
The problem is when people try to model classical OOP on top of
COM. This is one reason why on WinRT all classes implementing COM
are required to be final.