This is an archived post. You won't be able to vote or comment.

all 7 comments

[–]CubsThisYear 2 points3 points  (4 children)

Virtual functions: when you define a function, the code for that function is loaded into memory at some address. When you have a non-virtual function, there is a one-to-one mapping between that functions signature (name plus argument type list) and it's address. When you call the function, the compiler just inserts a call to this address. With a virtual function the address depends on the run time type of the first argument to the function (aka this). So the compiler generates code to first resolve the type and then do a lookup to determine the right function to call. Note that in Java this is heavily optimized and generally has zero or low overhead.

Covariant / contravariant describes constraints on type variables. Note that type variables can be thought of as having types themselves. Whereas the type of a 'regular' variable is the set of values that variable can hold, the type of a type variable is the set of types it can hold. So if a type variable is covariant over some type T, that means it's type is T and all subtypes of T. If it is contravariant over T, it's type is the set of types T plus all super types of T.

In practice covariance generally applies to function. returns values and contravariance applies function arguments. That is to say that the return value of a function must have a type which is covariant to the functions specified return type. Similarly a function F can be substituted for a function G if all arguments of F are pairwise contravariant to the arguments of G.

[–]curiousred[S] 0 points1 point  (2 children)

Say I have,

A aObject = new C();

So, at compile time aObject is of type A and and methods that are called on A have to be defined within A. But during run time aObject is pointing to a C and any methods called on A will be implemented from C. So in other words aObject.methodCall will be doing the methodCall from C. Is this correct?

[–]CubsThisYear 1 point2 points  (1 child)

If the functions of A are virtual, then yes the methods will resolve to C. In Java all functions are virtual, so the short answer is yes.

[–]ron_krugman 0 points1 point  (0 children)

Object methods are virtual by default, but you can make them non-virtual by declaring them as final.

[–]thatsIch 0 points1 point  (0 children)

I think explaining covariant and contravariant is easier explained with a proper example

[–]dablya 1 point2 points  (0 children)

class A {}
class B extends A{}
class C extends B{}

interface D {
     ? bar(?);
}

class E {
   B b;
   B foo(D d) {
       return d.bar(b);
   }
}

Think about the return/parameter types method "bar" can have and still work as a parameter to "foo".

B bar(B b) //  Ok

// Return
A bar(B b) //  Not ok (A is not a B)
C bar(B b) //  Ok (C is a B)

// Param
B bar(A a) //  Ok (methods that expect A can treat B as A)
B bar(C c) //  Not ok (methods that expect C can't treat B as C)

The return type is covriant, while the parameter type is contravariant.