Re: HashMap get/put



Mike Schilling wrote:
Peter Duniho wrote:

I think I see the disconnect here. I'm talking about the eventual
native code being executed. When possible (i.e. in C# for methods
that aren't explicitly marked as "virtual"), static calls are
generated, and thus they are non-virtual. But yes, you're
right...that's not really accurate, since the language itself doesn't
make the distinction in the _implementation_.

The C# compiler can create two completely different kiinds of code for mwthods that are not declared virtual. Consider the following file:

namespace Test
{
interface IFace
{
void Doit();
}
class Virtual : IFace
{
public void Doit()
{
}
public void DoitNow()
{
}
}
}

DoitNow is generated as a non-virtual method.

Well, you are using the same semantics I am. But as I pointed out, there's room for confusion here.

A call to DoitNow() still generates a "callvirt" MSIL instruction (similar to the Java approach). And in fact, you can change the implementation of your class Virtual so that DoitNow() is virtual and, after recompiling the assembly containing that class, a call site for the DoitNow() method in a completely different assembly will still work properly without itself being recompiled.

For example:

Assembly1.dll:
namespace Test
{
interface IFace
{
void Doit();
}
class Virtual : IFace
{
public void Doit()
{
}
public void DoitNow()
{
}
}
class Derived : Virtual
{
}
}

Program.exe:
namespace Test
{
class Test
{
public void Method()
{
Derived d = new Derived();

d.DoitNow();
}
}
}

In the above, Virtual.DoitNow() is what's called in Test.Method(). But, change DoitNow() to be virtual, add an override in Derived, and then rebuild Assembly1.dll. Without touching Program.exe, you still get the virtual method's override in Derived, because the call site is "virtual", whether the method is declared as "virtual" or not.

This is the behavior Thomas is talking about, and which is different from the context in which I'm describing the method as "virtual" or "not virtual". In particular, as far as the MSIL is concerned, _all_ method calls are "virtual" in the sense that there's essentially a vtable (not really, but that's how it looks in MSIL).

Doit is generated as a virtual method that cannot be overridden.

Sort of. It can be overridden if the original implementation is also declared as virtual. The question of whether it can be overridden or not isn't inherent to the implementation but rather is just a language restriction (similar to accessibility restrictions).

> This is completely
transparent to the C# programmer, whether the creator or consumer of these methods. Presumably it's done this way because a method needs to be virtual to be part of an interface implementation.

Yes, sort of. I agree with your description, but it's in conflict with the way Thomas and Patricia are talking about "virtual". In the respect of their comments, the method needs to be virtual because _all_ visible methods are virtual. The fact that it's an interface method doesn't really play a part. The method would be "virtual" regardless.

Now, once the JIT compiler gets ahold of the code, the interface method will (most likely, barring further optimization) remain virtual, called through an actual vtable-like data structure, while other "non-virtual" methods can be compiled as statically resolved call sites.

It's this latter characteristic of "virtual" that I was thinking of, but that wasn't the correct point of view given what Patricia meant.

The observstion I'd make here is that virtual vs. non-virtual is really an implementation artifact.

That really depends on which meaning of "virtual" you're talking about. Personally, I tend to look at the exposed language side, or the deepest implementation side (i.e. the native code). In both of those contexts, a method is either virtual or not. It may be virtual explicitly (because it's declared that way) or implicitly (because it's part of an interface). To me, the important thing is that you get the polymorphic behavior that arises from virtual methods.

In retrospect, reading that previous sentence I wrote, I suspect that my view is a carry-over from C++. Maybe it's not all that appropriate in the context of Java or C#, but I hold it nevertheless. :)

Anyway...

The point here is that Thomas and Patricia are looking not at the surface of the language, nor the final native implementation of the code, but rather what the syntax in the language represents in the context of the virtual machine that is expected to execute the code.

This isn't an unreasonable view. After all, the syntax of the language is just veneer, a way for us to express more simply the things we want the actual computer to do. And in Java the virtual machine _is_ the "computer" that we're instructing in this case; the actual native instruction set is just an optimization (and in fact, in Java the byte code may never wind up being compiled to native, just being interpreted instead).

In that view, the "virtual vs. non-virtual" is (as Thomas and Patricia point out) a non-existent distinction. If it exists at all, it necessarily must be an "implementation artifact".

As I said, that's not really the view I'm taking when I wrote about "virtual". From the syntactical point of view, I think there really is a difference between methods that are virtual and those that aren't. That is, a method is virtual if it can behave polymorphically and it's not if it can't. And in Java, we call the latter type "final". :)

But I at least see why Patricia wrote what she did, and I don't disagree with it, now that I understand the context in which the statement was intended to be understood.

The semantic difference between a non-virtual method and a virtual method that can't be overridden is nil (or nearly so.)

IMHO, it's a very strong semantic difference at the language level. It's what allows interfaces to have the same polymorphic behavior that virtual methods provide. With a non-virtual method ("final" in Java, just not "virtual" in C#), if you have an instance of the type in which that method is declared, you always get the implementation in that type. Period. But for a method declared in an interface, you can get any variety of implementations, depending on the actual implementor of the interface.

So, sure...unless the implementor has declared the implementation as "virtual" explicitly, sub-classes can't override it. But it's still providing the (IMHO vastly more) powerful feature of polymorphism. I consider that a pretty significant "semantic difference". :)

Pete
.



Relevant Pages

  • Re: Speed of interfaces vs inheritance
    ... implementation of an interface. ... Another thing to note is the degree of actual polymorphism at the call site. ... But that kind of optimisation makes considering call sites difficult. ... abstract public void abstractCall; ...
    (comp.lang.java.programmer)
  • Re: pls clarify important concepts...
    ... >>methods in that interface.. ... > public class MyClass implements MyInterface { ... > public void myMethod() { ... > public class UserDaoJDBC implements UserDao { ...
    (comp.lang.java.help)
  • Re: Correct use of State Pattern
    ... Unless you want to use reflection, you will probably need to have a different interface for each state. ... public void becomeImpregnated; ... public Tadpole hatch; ... public Frog metamorphose() { ...
    (comp.lang.java.programmer)
  • Re: Looking for a way to avoid use of instanceOf
    ... on the front of an interface name. ... unless there's an ordering on constraints. ... public void handle; ... You then add a method to RegulatedNME: ...
    (comp.lang.java.programmer)
  • Re: I dont understand inheritance!
    ... you can't override Interface methods that aren't marked as ... public abstract void DoSomething(); ... > IPostBackDataHandler (notice the interface that is implemented) ...
    (microsoft.public.dotnet.languages.csharp)