How a program can know which method use (polymorphism) - java

I have two classes
First class named Myclass This is the parent class
public class Myclass {
public static int x = 10;
static void printX() {
System.out.println("From the Superclass x = " + x);
}
}
Second class named MySecondClass This the child class
public class MySecondClass extends Myclass {
static void printX() {
System.out.print("From the Subclass x = " + x);
}
public static void main(String[] args) {
printX();
}
}
As a newbie in Java Programming, I want to understand the Polymorphism; How can it choose between the two methods printX()? And in the code above why does it choose the MySecondClass method ?

Welcome to the community.
What you are trying to do here is called overriding. Although in reality java does not allow static methods to be overridden. If you instantiate the child class and call "printX" it will call the overridden method in the child class.
IE: From the Subclass x = .
But if you instantiate the parent class and call the method it will print "From the Superclass"
Although in this scenario what you are doing is not "overriding" as the methods are static. But this approach is called "method hiding"
To answer your question, it chose the second method because the second method (child class method) has hidden your super class method.

If methods are static, then it is determined at compile time which method is called, based on the class involved in the call.
If methods are instance members, then the relevant method body is looked up by its signature on the instance's concrete class, at runtime, falling back progressively upward on super classes until found. Consider that a simple map of signature-to-functionpointer, in each class and super classes, if you prefer.

Related

#Override on static methods? [duplicate]

I'd like to know:
Why can't static methods be overridden in Java?
Can static methods be overloaded in Java?
Static methods can not be overridden in the exact sense of the word, but they can hide parent static methods
In practice it means that the compiler will decide which method to execute at the compile time, and not at the runtime, as it does with overridden instance methods.
For a neat example have a look here.
And this is java documentation explaining the difference between overriding instance methods and hiding class (static) methods.
Overriding: Overriding in Java simply means that the particular method would be called based on the run time type of the object and
not on the compile time type of it (which is the case with overriden
static methods)
Hiding: Parent class methods that are static are not part of a child class (although they are accessible), so there is no question of
overriding it. Even if you add another static method in a subclass,
identical to the one in its parent class, this subclass static method
is unique and distinct from the static method in its parent class.
Static methods can not be overridden because there is nothing to override, as they would be two different methods. For example
static class Class1 {
public static int Method1(){
return 0;
}
}
static class Class2 extends Class1 {
public static int Method1(){
return 1;
}
}
public static class Main {
public static void main(String[] args){
//Must explicitly chose Method1 from Class1 or Class2
Class1.Method1();
Class2.Method1();
}
}
And yes static methods can be overloaded just like any other method.
Static methods cannot be overridden because they are not dispatched on the object instance at runtime. The compiler decides which method gets called.
This is why you get a compiler warning when you write
MyClass myObject = new MyClass();
myObject.myStaticMethod();
// should be written as
MyClass.myStaticMethod()
// because it is not dispatched on myObject
myObject = new MySubClass();
myObject.myStaticMethod();
// still calls the static method in MyClass, NOT in MySubClass
Static methods can be overloaded (meaning that you can have the same method name for several methods as long as they have different parameter types).
Integer.parseInt("10");
Integer.parseInt("AA", 16);
Parent class methods that are static are not part of a child class (although they are accessible), so there is no question of overriding it. Even if you add another static method in a subclass, identical to the one in its parent class, this subclass static method is unique and distinct from the static method in its parent class.
Static methods can not be overridden because they are not part of the object's state. Rather, they belongs to the class (i.e they are class methods). It is ok to overload static (and final) methods.
Overloading is also called static binding, so as soon as the word static is used it means a static method cannot show run-time polymorphism.
We cannot override a static method but presence of different implementations of the same static method in a super class and its sub class is valid. Its just that the derived class will hide the implementations of the base class.
For static methods, the method call depends on the type of reference and not which object is being referred, i.e. Static method belongs only to a class and not its instances , so the method call is decided at the compile time itself.
Whereas in case of method overloading static methods can be overloaded iff they have diff number or types of parameters. If two methods have the same name and the same parameter list then they cannot be defined different only by using the 'static' keyword.
If I m calling the method by using SubClass name MysubClass then subclass method display what it means static method can be overridden or not
class MyClass {
static void myStaticMethod() {
System.out.println("Im in sta1");
}
}
class MySubClass extends MyClass {
static void myStaticMethod() {
System.out.println("Im in sta123");
}
}
public class My {
public static void main(String arg[]) {
MyClass myObject = new MyClass();
myObject.myStaticMethod();
// should be written as
MyClass.myStaticMethod();
// calling from subclass name
MySubClass.myStaticMethod();
myObject = new MySubClass();
myObject.myStaticMethod();
// still calls the static method in MyClass, NOT in MySubClass
}
}
No,Static methods can't be overriden as it is part of a class rather than an object.
But one can overload static method.
Static methods are a method whose single copy is shared by all the objects of the class. A static method belongs to the class rather than objects. since static methods are not dependent on the objects, Java Compiler need not wait till the creation of the objects so to call a static method we use syntax like ClassName.method() ;
In the case of method overloading, methods should be in the same class to overload.even if they are declared as static it is possible to overload them as,
Class Sample
{
static int calculate(int a,int b,int c)
{
int res = a+b+c;
return res;
}
static int calculate(int a,int b)
{
int res = a*b;
return res;
}
}
class Test
{
public static void main(String []args)
{
int res = Sample.calculate(10,20,30);
}
}
But in the case of method overriding, the method in the super class and the method in the sub class act as a different method. the super class will have its own copy and the sub class will have its own copy so it does not come under method overriding.
class SuperType {
public static void classMethod(){
System.out.println("Super type class method");
}
public void instancemethod(){
System.out.println("Super Type instance method");
}
}
public class SubType extends SuperType{
public static void classMethod(){
System.out.println("Sub type class method");
}
public void instancemethod(){
System.out.println("Sub Type instance method");
}
public static void main(String args[]){
SubType s=new SubType();
SuperType su=s;
SuperType.classMethod();// Prints.....Super type class method
su.classMethod(); //Prints.....Super type class method
SubType.classMethod(); //Prints.....Sub type class method
}
}
This example for static method overriding
Note: if we call a static method with object reference, then reference type(class) static method will be called, not object class static method.
Static method belongs to class only.
static methods are class level methods.
Hiding concept is used for static methods.
See : http://www.coderanch.com/how-to/java/OverridingVsHiding
The very purpose of using the static method is to access the method of a class without creating an instance for it.It will make no sense if we override that method since they will be accessed by classname.method()
No, you cannot override a static method. The static resolves against the class, not the instance.
public class Parent {
public static String getCName() {
return "I am the parent";
}
}
public class Child extends Parent {
public static String getCName() {
return "I am the child";
}
}
Each class has a static method getCName(). When you call on the Class name it behaves as you would expect and each returns the expected value.
#Test
public void testGetCNameOnClass() {
assertThat(Parent.getCName(), is("I am the parent"));
assertThat(Child.getCName(), is("I am the child"));
}
No surprises in this unit test. But this is not overriding.This declaring something that has a name collision.
If we try to reach the static from an instance of the class (not a good practice), then it really shows:
private Parent cp = new Child();
`enter code here`
assertThat(cp.getCName(), is("I am the parent"));
Even though cp is a Child, the static is resolved through the declared type, Parent, instead of the actual type of the object. For non-statics, this is resolved correctly because a non-static method can override a method of its parent.
You can overload a static method but you can't override a static method. Actually you can rewrite a static method in subclasses but this is not called a override because override should be related to polymorphism and dynamic binding. The static method belongs to the class so has nothing to do with those concepts. The rewrite of static method is more like a shadowing.
I design a code of static method overriding.I think It is override easily.Please clear me how its unable to override static members.Here is my code-
class Class1 {
public static int Method1(){
System.out.println("true");
return 0;
}
}
class Class2 extends Class1 {
public static int Method1(){
System.out.println("false");
return 1;
}
}
public class Mai {
public static void main(String[] args){
Class2 c=new Class2();
//Must explicitly chose Method1 from Class1 or Class2
//Class1.Method1();
c.Method1();
}
}
It’s actually pretty simple to understand – Everything that is marked static belongs to the class only, for example static method cannot be inherited in the sub class because they belong to the class in which they have been declared. Refer static keyword.
The best answer i found of this question is:
http://www.geeksforgeeks.org/can-we-overload-or-override-static-methods-in-java/
As any static method is part of class not instance so it is not possible to override static method
From Why doesn't Java allow overriding of static methods?
Overriding depends on having an instance of a class. The point of polymorphism is that you can subclass a class and the objects implementing those subclasses will have different behaviors for the same methods defined in the superclass (and overridden in the subclasses). A static method is not associated with any instance of a class so the concept is not applicable.
There were two considerations driving Java's design that impacted this. One was a concern with performance: there had been a lot of criticism of Smalltalk about it being too slow (garbage collection and polymorphic calls being part of that) and Java's creators were determined to avoid that. Another was the decision that the target audience for Java was C++ developers. Making static methods work the way they do have the benefit of familiarity for C++ programmers and were also very fast because there's no need to wait until runtime to figure out which method to call.
Definitely, we cannot override static methods in Java.
Because JVM resolves correct overridden method based upon the object at run-time by using dynamic binding in Java.
However, the static method in Java is associated with Class rather than the object and resolved and bonded during compile time.

Is it possible for a superclass object to refer a subclass member method which is not inherited?

In dynamic method binding a superclass reference can only call a subclass method which is inherited and overrode by it. However, the otherwise can be implemented.
abstract class in
{
abstract void print();
}
class a extends in
{
String name=this.getClass().getSimpleName();
void show()
{
System.out.println("class "+name);
}
void print()
{
show();
}
}
class Main
{
public static void main(String args[])
{
in x;
x = new a();
x.print();
}
}
Here, it prints successfully
class a
Also getClass() returns the subclass name instead of superclass name as this refers to the superclass object in main method.
A parent object reference is just constrained by the methods that it has in its class definition. If those methods are overridden by subclass, and at run time, if the actual object referred by the parent reference is of subclass type, then that overridden method is invoked. It doesn't matter if the overridden method invokes methods that are not originally present in the parent class or accesses the variables that are not present in the parent class.
This is what polymorphism is all about. It is by design meant to be this way as it makes program extension easier in case if we have different specific inheritance hierarchies where the parent class need not know the exact implementation of certain methods and can make things implemented by the subclasses as some sort of contract.
Future is unknown A developer writing a class A.java today can never predict in future the names or signatures of the methods which any other developer may include in his class extending A.java. Also such classes may be numerous with each having separate methods.
Base class should never be coupled with its sub classes. It must not care about how the sub classes are implemented.
Although it is not recommended but still if you wish to invoke the method defined in one of the sub class you may do it by typecasting like below.
public class Parent {
public class someMethod(){
if( this instanceof Child1){
((Child1)this).someAdditionalMethod();
}
}
}
public class Child1 extends Parent{
public class someAdditionalMethod(){
}
}

Difference between super keyword vs class name to call method from super class

Kindly excuse my question as I have tried to search the difference between using super keyword vs class name to call a method from super class but am unable to find an answer.
My question is I am trying to learn Java as a study course and am using an example from the link: http://www.javatpoint.com/super-keyword using Example # 3 and here is the code I have written:
I have created a super class named Vehicle
public class Vehicle {
Vehicle() {
System.out.println("Vehicle constructor created");
}
public void speed() {
int a = 20;
System.out.println(a);
}
}
and then created a sub class named Bike with the following code:
public class Bike extends Vehicle {
int speed;
Bike(int speed1) {
this.speed = speed1;
System.out.println(speed1);
super.speed();
}
public static void main(String args[]) {
Bike b = new Bike(10);
}
}
In the sub class under Bike constructor I am using super.speed() to call speed method from super (Vehicle) class. Now if I change this line to Vehicle.speed() I get an error stating that I need to make my speed method as static.
I do not want to make my method as static and want to know about the difference between both of them.
Cheers,
Calling a method using class name directly means that you want to call a static method, which is not related to any object of the class but the class it self.
That is why the compiler tells you that the method must be static.
As for your question, when you create an object of a child class (Bike class in this example) an object of its parent is always created, on the base of which the particular child object is created.
Its like, when ever you create a Bike, a backing Vehicle is always created, based on which the Bike is created. Otherwise the Bike wouldn't be a Vehicle.
So calling a method by super means, you're telling the compiler to call this method on the class which was used as base(parent) for making this Bike class, from which I'm calling this method.
when you're calling the method by class name, you're telling the compiler to call this method of Vehicle class which is not related to any Vehicle object/instance (and obviously not related to any child (e.g. Bike object or instance as well)
Methods that aren't static can only be called on a specific instance of an object. That is why calling Vehicle.speed() would only work if the speed method were static. The reason you can call super.speed() is because in the constructor, you have already constructed the vehicle object, and are basically calling the method on the object you are constructing.
For the above example, I would say that calling super.speed() is the best approach.
Also, as you haven't overriden the super implementation of the speed method, you can just as easily call this.speed() or speed(). That approach would mean that if you ever decided that the Bike needs different functionality in the speed method, your specific implementation would be called as opposed to the default.
The two constructs are not equivalent.
When calling Vehicle.speed() the compiler is looking for a static method named speed() in the class named Vehicle. A static method doesn't belong to any instance of the class. You cannot use any instance variable inside a static method. You haven't defined a static method named speed() in your Vehicle class and therefore there's no such thing as Vehicle.speed(). Hence, you get a compilation error.
When calling super.speed(), you don't look for a static method as in the previous case: The actual method that is going to be called when using the super syntax is an instance method (named speed() in your case) defined in the superclass of the current object. That is, super.speed() is the instance method defined in the super class of the current object (unlike this.speed() which is the instance method named speed() defined in the actual class of the current object). In other words, it is going to call the method speed() defined in the class Vehicle, but the this parameter is going to be the one referenced by b, the current object.
You need instance to calls instance(non-static) method.
super is parent class's instance. Simply put class name is not an instance(it' a static context for entire class).
[super is parent class's instance ?]
Jon skeet said no such thing as a "parent instance", but i doubt the term of instance.
super's variable is initialized first and then the turns of child to decide whether share the same variable/method(i.e. return this.i; in this kind of method will return super.i, not this.i, when call by child) or override it.
import java.util.Random;
class Love {
int i = 1;
int hole() {
return this.i;
}
}
class Main extends Love {
void wrapper() {
System.out.println(super.i); //1
System.out.println(this.i); //2
super.i = new Random().nextInt(50) + 2; //to avoid compiler pre-optimizing hard coded return value in hole(), so we set again.
System.out.println(super.i); //23
i = 3; //2nd attempt override
this.i = 3; //3rd attempt override
System.out.println(hole()); //23, super "instance" keep its own version of this.i
}
int i = 2; //1st attempt oveeride
public static void main(String[] args) {
new Main().wrapper();
}
}
So it's obvious when child override, super still keep its own version, so IMHO super can roughly treat like a parent instance, just the difference with normal instance are it's a keyword with some restriction of usage (e.g. super.super.i is not allow, direct print super not allow). One more difference is the variable value will sync in each instance due to child might share it as mentioned above.
You can try to print super.variable_name inside static method, it will output super is a non-static variable:
$ javac Bike.java
Bike.java:132: error: non-static variable super cannot be referenced from a static context
System.out.println(super.dummy);
^
Bike.java:132: error: cannot find symbol
System.out.println(super.dummy);
^
symbol: variable dummy
2 errors
$
So it's make sense super as a non-static variable can access non-static method speed() in your example.
If you want to use method directly with class name then you have to specify method as static
public static void speed() {
int a = 20;
System.out.println(a);
}
or
you can create an object of class Vehicle and access speed method in your subsclass like this
Bike(int speed1) {
this.speed = speed1;
System.out.println(speed1);
Vehicle vehicle = new Vehicle();
vehicle.speed();
}
hi super is a keyword which is used to access the super class methods in sub class.
This super keyword is used mainly when methods are overridden.
example
class A
{
method m()
}
class B extends A
{
method m()
method m1()
{
super.m()
}
}
class C
{
public static void main(String args[])
{
B b = new B();
b.m() // calls method m() in class B
b.m1() // calls method m() in class A because method m is pointing to super class method
}
}

java inheritance misunderstanding

The first question is inside the code. The second question is why static methods can't be overridden to be non-static methods? The third is why can't static and abstract go together?
class A {
public void display() {
System.out.println("Display of Class A called");
}
}
class B extends A {
public void display() {
System.out.println("Display of Class B called");
}
}
class C extends B {
public void display() {
System.out.println("Display of Class C called");
super.display(); // calls B's Display
// Is there a way to call A's display() from here?
}
}
[B] // Is there a way to call A's Display from here???[/B]
No, you can't go two steps up in the class hierarchy. You could implement and call a method in B which would invoke the A implementation.
why static methods can't be overridden to be non-static methods
static methods are associated with a class. Polymorphism (and thus overriding) is a concept that applies to objects and therefore does not apply to them.
why can't static and abstract go together
For the same reason given above. An abstract method is a method that should be implemented in a sub class because the sub class inherited it. Since a sub class does not inherit a static method, a static method cannot be abstract.
First question: no you can't call the bass class's bass class directly, since in class C's view, it has no idea that class B has a bass class and it's class A. All that's know by C is that it has a base class, and it's B.
Second question: static methods are simply a neat way to organize global methods. There's no inheritance. You just put that method to a class so when you write code to call it, you know where to locate it.
Third question: abstract means "this is what the class to do, here are some basic functionality, but I cannot finish this; inherit me and finish whatever is left to get it working". As mentioned earlier, static method is just a way to put methods that "stand by themselves", requires no initialization and no context. The two does not go together.

Can I know the extending class from the super class in Java?

I have the following classes.
public class Super{
public static void useSubClass(){
//I want to access the sub class object here, how.
}
}
public class Sub1 extends Super{
}
public class Sub2 extends Super{
}
I want to access the sub-class object from a static method in super-class. i.e. When I call Sub1.useSubClass() the method has access to Sub1.class and when I use Sub2.useSubClass(), I can access the Sub2.class.
Is there any way to access the sub-class object from super-class.
In general, you cannot do that from a superclass (and shouldn't!) because you won't know (and shouldn't assume anything about!) what classes will inherit from your superclass.
Depending on exactly what you want to do, there are alternatives, such as:
Use the template pattern to define "filler methods" that your subclasses must implement; these filler methods will be called by the template method in your superclass.
Define methods to be overridden by your subclass.
Define interfaces to be implemented by your subclass.
Update: As #JB Nizet has pointed out, I might have misread the question.
Here's something (very similar to the Observer Pattern) you can do if you wish to access subclasses from the static method in your superclass:
Define a static listener list in your superclass, call it List observerList
In the constructor of your superclass, add the class instance itself to that static observerList
For all subclasses, it is their responsibility to call super() from their constructors in order to register themselves to observerList (and unregister in deconstructor)
Then in your superclass's static useSubClass() method, you can iterate through that list of subclass instances, find the particular one you care about (maybe specified by some argument), and then do something with it.
Static methods are not inherited, and calling Sub2.useSubClass() is strictly equivalent to calling Super.useSubclass().
There is no way to get this information, because it doesn't exist. The compiler allows calling Sub2.useSubclass(), but translates it into Super.useSubclass().
public static void useSubClass(Super sub) {
if (sub instanceof Sub1) {
// Do something
} else if (sub instanceof Sub2) {
// Do something else
} else {
// Something else is extending Super
}
}
However, a better question is why? Can't you simply override the method in your subclass?
No you cannot because the super-class cannot know the methods of the sub-classes.
You should consider to create a new class which sees both super-class and sub-classes and implement the static method inside this new class
For the record, you could do this in Python, using class methods:
class super(object):
#classmethod
def usesubclass(cls):
print cls
class sub1(super):
pass
class sub2(super):
pass
Using this code, you could call sub1.usesubclass() or sub2.usesubclass(), and that would print the representations of the sub1 and sub2 classes, respectively:
>>> sub1.usesubclass()
<class '__main__.sub1'>
>>> sub2.usesubclass()
<class '__main__.sub2'>
Java, however, does not support such mechanisms, unfortunately. When you compile Sub1.useSubClass() in your example, the compiler will simply use Sub1 as the basic namespace to look up the the useSubClass() method in Super, but no information on that is actually compiled into code. In the resulting bytecode, the call is simply one directly to Super.useSubClass() and nothing more.
I sympathize with your plight, but Java is what it is. The closest thing you could come, I think, would be the following code:
public class Super {
public static <T extends Super> void useSubClass(Class<T> sub) {
}
}
And then call that method explicitly as either Super.useSubClass(Sub1.class) or Super.useSubClass(Sub2.class).
I figured something out. It works if implemented with care.
/** SuperClass.java **/
public abstract class SuperClass {
public static void printClass(){
System.out.println(new ImplementingClassRetriever().getCallingClass());
}
static class ImplementingClassRetriever extends SecurityManager{
public Class getCallingClass() {
Class[] classes = getClassContext();
for (Class clazz : classes) {
if (SuperClass.class.isAssignableFrom(clazz) && clazz != null
&& !clazz.equals(SuperClass.class)) {
return clazz;
}
}
return null;
}
}
}
/** Main.java **/
public class Main{
public static void main(String[] args) {
Sub.printClass(); //this does not work
Sub.testStaticCall(); //this works!! :)
}
}
class Sub extends SuperClass{
public static void testStaticCall(){
Sub.printClass(); //calling the method in the super class
}
}
This is just a toy example. The super class contains a static class that contains a method to retrieve the calling class.
In the subclass I have another static method which calls the superclass's method for printing the class name.
The Main class/function contains two calls to Sub's inherited and locally implemented method. The first call prints null, because the calling context (i.e. Main) is not a subclass of Super However the delegate method in Sub works because the calling context is now a subclass of SuperClass and hence the calling class can be determined.
Although You can create a reference to the super class and point it to any sub-class. This can also be done dynamically during run-time. This is a way of run-time polymorphism.

Categories

Resources