Is it possible to write virtual methods in Java, as one would do in C++?
Or, is there a proper Java approach which you can implement that produces similar behavior? Could I please have some examples?
From wikipedia
In Java, all non-static methods are by
default "virtual functions." Only
methods marked with the keyword final,
which cannot be overridden, along with
private methods, which are not
inherited, are non-virtual.
Can you write virtual functions in Java?
Yes. In fact, all instance methods in Java are virtual by default. Only certain methods are not virtual:
Class methods (because typically each instance holds information like a pointer to a vtable about its specific methods, but no instance is available here).
Private instance methods (because no other class can access the method, the calling instance has always the type of the defining class itself and is therefore unambiguously known at compile time).
Here are some examples:
"Normal" virtual functions
The following example is from an old version of the wikipedia page mentioned in another answer.
import java.util.*;
public class Animal
{
public void eat()
{
System.out.println("I eat like a generic Animal.");
}
public static void main(String[] args)
{
List<Animal> animals = new LinkedList<Animal>();
animals.add(new Animal());
animals.add(new Fish());
animals.add(new Goldfish());
animals.add(new OtherAnimal());
for (Animal currentAnimal : animals)
{
currentAnimal.eat();
}
}
}
class Fish extends Animal
{
#Override
public void eat()
{
System.out.println("I eat like a fish!");
}
}
class Goldfish extends Fish
{
#Override
public void eat()
{
System.out.println("I eat like a goldfish!");
}
}
class OtherAnimal extends Animal {}
Output:
I eat like a generic Animal.
I eat like a fish!
I eat like a goldfish!
I eat like a generic Animal.
Example with virtual functions with interfaces
Java interface methods are all virtual. They must be virtual because they rely on the implementing classes to provide the method implementations. The code to execute will only be selected at run time.
For example:
interface Bicycle { //the function applyBrakes() is virtual because
void applyBrakes(); //functions in interfaces are designed to be
} //overridden.
class ACMEBicycle implements Bicycle {
public void applyBrakes(){ //Here we implement applyBrakes()
System.out.println("Brakes applied"); //function
}
}
Example with virtual functions with abstract classes.
Similar to interfaces Abstract classes must contain virtual methods because they rely on the extending classes' implementation. For Example:
abstract class Dog {
final void bark() { //bark() is not virtual because it is
System.out.println("woof"); //final and if you tried to override it
} //you would get a compile time error.
abstract void jump(); //jump() is a "pure" virtual function
}
class MyDog extends Dog{
void jump(){
System.out.println("boing"); //here jump() is being overridden
}
}
public class Runner {
public static void main(String[] args) {
Dog dog = new MyDog(); // Create a MyDog and assign to plain Dog variable
dog.jump(); // calling the virtual function.
// MyDog.jump() will be executed
// although the variable is just a plain Dog.
}
}
All functions in Java are virtual by default.
You have to go out of your way to write non-virtual functions by adding the "final" keyword.
This is the opposite of the C++/C# default. Class functions are non-virtual by default; you make them so by adding the "virtual" modifier.
All non-private instance methods are virtual by default in Java.
In C++, private methods can be virtual. This can be exploited for the non-virtual-interface (NVI) idiom. In Java, you'd need to make the NVI overridable methods protected.
From the Java Language Specification, v3:
8.4.8.1 Overriding (by Instance Methods) An instance method m1
declared in a class C overrides
another instance method, m2, declared
in class A iff all of the following
are true:
C is a subclass of A.
The signature of m1 is a subsignature (§8.4.2) of the signature
of m2.
Either
* m2 is public, protected or declared with default access in the
same package as C, or
* m1 overrides a method m3, m3 distinct from m1, m3 distinct from
m2, such that m3 overrides m2.
Yes, you can write virtual "functions" in Java.
In Java, all public (non-private) variables & functions are Virtual by default.
Moreover variables & functions using keyword final are not virtual.
Related
class Bank{
float getRateOfInterest(){return 0;}
}
class SBI extends Bank{
float getRateOfInterest(){return 8.4f;}
}
class TestPolymorphism{
public static void main(String args[]){
Bank a = new SBI();
SBI b = new SBI();
a.getRateOfInterest();
b.getRateOfInterest();
}
}
a.getRateOfInterest() and b.getRateOfInterest() both gives same output. So what is the difference between both the statements?
I think 1st is upcasting.
Java methods are all virtual, so the method called depends on the run-time type of the called object, not on the compile-time type of the variable holding the reference.
It's not, if you construct it with new SBI(). It'll always return 8.4f.
All java method is virtual (by design).
They rely on the implementing classes to provide the method implementations.
Here is more information.
- Can you write virtual functions / methods in Java?
- https://en.wikipedia.org/wiki/Virtual_function
Here is an excerpt from wikipedia :-
public class Animal {
public void eat() {
System.out.println("I eat like a generic Animal.");
}
public static void main(String[] args) {
Animal animal=new Wolf ();
animal.eat(); //print "I eat like a wolf!
}
}
class Wolf extends Animal {
#Override
public void eat() {
System.out.println("I eat like a wolf!");
}
}
Virtual functions are resolved 'late'. If the function in question is
'virtual' in the base class, the most-derived class's implementation
of the function is called according to the actual type of the object
referred to, regardless of the declared type of the pointer or
reference. If it is not 'virtual', the method is resolved 'early' and
the function called is selected according to the declared type of the
pointer or reference.
Virtual functions allow a program to call methods that don't
necessarily even exist at the moment the code is compiled.
From the docs, "If a subclass defines a static method with the same signature as a static method in the superclass, then the method in the subclass hides the one in the superclass."
I understand the difference between method hiding and overriding. However, it's strange to say that the subclass hides the superclass method because if you have the following:
public class Cat extends Animal {
public static void testClassMethod() {
System.out.println("The static method in Cat");
}
public void testInstanceMethod() {
System.out.println("The instance method in Cat");
}
public static void main(String[] args) {
Cat myCat = new Cat();
Animal myAnimal = myCat;
Animal.testClassMethod();
myAnimal.testInstanceMethod();
}
}
The superclass's static method is called. But by the definition of hiding, the method in the subclass is hiding the one in the superclass. I don't see how the subclass is "covering up/hiding" the superclass static method, as the superclass's method is the one that's actually called.
The superclass's static method is called.
Yes. But that is because you explicitly named the superclass's static method by qualifying with the superclass name in the call statement.
If you had written the main like this instead:
public static void main(String[] args) {
...
testClassMethod();
}
then you would have seen that the Cat version of testClassMethod was called. Here, the Cat.testClassMethod method hides the Animal.testClassMethod method
Cat's testClassMethod() hides Animal.testClassMethod(), since if you didn't have a static testClassMethod() in the Cat class, Cat.testClassMethod() would invoke Animal.testClassMethod().
When you call Animal.testClassMethod(), it's can't be hidden by a sub-class's method.
I think it's called "hiding" because you can no longer access the superclass's method simply by writing the method name. Without the public static void testClassMethod() definition in Cat, your main could say
testClassMethod();
to call the method defined in Animal. But you can no longer do that. Yes, you can still call it by giving it the qualified name:
Animal.testClassMethod();
so it's not completely hidden. But please note that people who write language standards have to come up with names for some concepts that may not quite match the meanings we give words in the non-computing world, so sometimes coming close is the best they can do. You can't try to take the terminology literally. The term hidden has a formal definition somewhere in the JLS, I believe; and that means when you see the term used in the JLS, it means whatever the JLS defines it to mean, neither more nor less.
Consider adding this to your posted example
class Dog extends Animal {
// nothing here
}
Now if you do this:
new Cat().testClassMethod();
new Dog().testClassMethod();
each of the above will give different output. So you could say that the static method in Cat did hide the Animal's static method - while there's no such thing as overriding for static methods, one of the animals printed according to Animal's code and the other did not.
(P.S. I'm definitely not encouraging you to call static methods in this way.)
Imagine following code:
public class BaseClass {
private int a;
public void noReturnNoParam() {
System.out.println("From Base Class");
}
}
public class ExtendedClass extends BaseClass {
private int b;
#Override
public void noReturnNoParam() {
System.out.println("From Extended Class");
}
}
public class Polymorph {
public static void main(String... args) {
BaseClass bc = new BaseClass();
ExtendedClass ec = new ExtendedClass();
BaseClass bcec = new ExtendedClass();
bc.noReturnNoParam();
ec.noReturnNoParam();
bcec.noReturnNoParam();
}
}
Output is as follows:
From Base Class
From Extended Class
From Extended Class
So how can I achieve that, on calling bcec.noReturnNoParam() the BaseClass` method is called? (and only if the ExtendedClass object is stored in a BaseClass type)?
That's exactly the concept of polymorphism:
BaseClass bcec = new ExtendedClass();
BaseClass is the contract you declared for bcec. It give your compile time information about what you can get from bcec. It tells you that you can call noReturnNoParam method.
ExtendedClass is the actually implementation of bcec. JVM know at runtime that bcec.noReturnNoParam() is invoking the noReturnNoParam in ExtendedClass.
The below statement is similar:
ExtendedClass ec = new ExtendedClass();
ExtendedClass on the left is the contract, tells you what you can get from ec. ExtendedClass on the right is the actual implementation, which is executed at runtime.
ExtendedClass extends BaseClass, so an instance of ExtendedClass is also an instance of BaseClass. But an instance of BaseClass might not be an instance of ExtendedClass. That's why the below cannot compile:
ExtendedClass abc = new BaseClass();
I give you another example to make the concept less abstract.
class Fruit {
void taste() {
System.out.println("delicious!");
}
}
class Apple extends Fruit{
void taste() {
System.out.println("sweet!");
}
}
class Orange extends Fruit{
void taste() {
System.out.println("juicy!");
}
}
class Polymorph {
public static void main(String... args) {
Fruit fruit = new Fruit();
Apple apple = new Apple();
Fruit fruit_apple = new Apple();
Fruit fruit_orange = new Orange();
fruit.taste(); // prints delicious!
apple.taste(); // prints sweet!
fruit_apple.taste(); // prints sweet!
fruit_orange.taste(); // prints juicy!
}
}
Orange and Apple are both Fruit. Fruit/Orange/Apple all have tastes, and Orange and Apple have their own tastes. You say an apple is a kind of fruit, an orange is also a kind of fruit, but you can't say a fruit is an apple.
This is called Dynamic Polymorphism \ Dynamic method binding in which at runtime,
JVM call method of object type, NOT reference type. In this case object type is ExtendedClass, hence its calling method from that class.
And you cant avoid it.
The issue you are having is with static vs dynamic binding.
With dynamic binding, methods will be dynamically called at run-time. Here's a good little article to read if you need clarification.
To my knowledge, you wont be able to strictly call the base method the way your classes are currently designed. Only from the derived class' method can you call the base class' since you are overriding it.
So, even though you are declaring it for the compiler as the base class, the object is really an object of the derived class, and as such, its methods will be called during run-time.
This is demonstration of one of the base principles OOP. It is called polymorphism.
Independent of how your class(BaseClass in your example) looks like it will work as it class which was used for initialisation(ExtendedClass).
This is not what intended from Polymorphism. Any way you can make your extended class to call its super class implementation in its method like
#Override
public void noReturnNoParam() {
super.noReturnNoParam(); // here base class implementation will be run
System.out.println("From Extended Class");
}
But you cannot make it to call only base class implementation.
The Java virtual machine (JVM) calls the appropriate method for the
object that is referred to in each variable. It does not call the
method that is defined by the variable's type. This behavior is
referred to as virtual method invocation and demonstrates an aspect of
the important polymorphism features in the Java language.
Sorry to bring back the dead. But I still don't clearly understand what this section of specification states.
If an interface has no direct superinterfaces, then the interface
implicitly declares a public abstract member method m with signature
s, return type r, and throws clause t corresponding to each public
instance method m with signature s, return type r, and throws clause t
declared in Object, unless a method with the same signature, same
return type, and a compatible throws clause is explicitly declared by
the interface. It is a compile-time error if the interface explicitly
declares such a method m in the case where m is declared to be final
in Object.
Given
interface Testing
{
void test();
}
public class Test{
public static void main(String[] args) {
Testing t = new Testing(){
#Override
public void test(){
}
};
t.test();
t.toString();
}
}
Now as the spec states that the above will change to
interface Testing
{
void test();
String toString();
//other non-final methods of Object
}
public class Test{
public static void main(String[] args) {
Testing t = new Testing(){
#Override
public void test(){
}
};
t.test();
t.toString();
}
}
Also. please confirm if there is an hierarchy of interfaces then all of them get these abstract methods.
What it means is that every class extends Object (at some point in its class heirarchy). However, interfaces do not extend Object. This is to avoid the problems that arise from multiple inheirtance.
Since interfaces do not extend Object that would mean we were unable to use methods like toString if the type (not class) of the object we had access to was an interface. But we know those methods must be available since all classes at some point extend from Object. Therefore, to get around this problem all of Object's not final methods are implicitly declared in all interfaces that have no superinterfaces. These contracts of these methods are always satisfied since all classes must at some point extend from Object.
TL;DR -- it's a trick to make sure we can access the methods made available by Object when we have an instance of some class stored in variable that's type is an interface (eg. Serializable)
edit: To answer your question, You're slightly off. All non-final methods of Object are added to an interface (whether they are used or not) if that interface has no parent interface AND for each method to added: that there is no matching method is explicitly declared by the interface.
As long as there is no super interface to an interface it gets the implicit declaration of the Object class methods. As long as these methods are included in the interface. Every interface that either extends or implements this interface doesn't see much difference between the methods that are explicitly declared by this interface or it got implicitly. That point forward that interface is as good as declared them explicitly.
Recently came across an interesting feature, which, though, can result in a unexpected output of Eclipse "add unimplemented methods" feature. What is the "googl-able" name of the language concept behind this "occasional implicit implementation"?
I wouldn't expect the code below to compile but it did and is working
interface CallmeIfc {
public void callme();
}
class CallmeCode {
public void callme() {
// implementation
}
}
class CallmeImpl extends CallmeCode implements CallmeIfc {
// empty class body
}
public static void main(String[] args) {
CallmeIfc me = (CallmeIfc) new CallmeImpl();
me.callme(); // calls CallmeCode.callme()
}
In CallmeImpl, the public callme() method is inherited from CallmeCode, so CallmeImpl respects the contract defined in the CallmeIfc.
Then, in your main() method, polymorphism allows you to assign a subclass instance (CallmeImpl) to a superclass or superinterface reference - in this particular case, the "me" reference, of type CallmeIfc (you have a typo here, BTW).
Actually this looks like a compiler bug to me: The Java Language Specification writes:
An instance method m1 declared in a
class C overrides another instance
method, m2, declared in class A iff
all of the following are true:
C is a subclass of A.
The signature of m1 is a subsignature (§8.4.2) of the signature of m2.
Either
m2 is public, protected or declared with default access in the same package as C, or
m1 overrides a method m3, m3 distinct from m1, m3 distinct from m2, such that m3 overrides m2.
In your case, the first condition is not satisfied: The method callme is declared in class CallMeCode, which is not a subtype of CallmeIfc.
Edit: Bobah is right, the Spec distinguishes between implementing and overriding. In fact, it actually mandates the observed behaviour:
Unless the class being declared is
abstract, the declarations of all the
method members of each direct
superinterface must be implemented
either by a declaration in this class
or by an existing method declaration
inherited from the direct superclass,
because a class that is not abstract
is not permitted to have abstract
methods
The Spec does not explain why.
Although CallmeCode class doesn't implement the CallmeIfc interface, it provides the necessary implementation. It is as if class CallmeCode implements the interface. It would have worked also with this code:
interface CallmeIfc {
public void callme();
}
class CallmeCode implements CallmeIfc {
public void callme() {
// implementation
}
}
class CallmeImpl extends CallmeCode implements CallmeIfc {
// empty class body
}
In your case this is fine because class CallmeCode has a method callme. If the method would have been named different it wouldn't compile.