static binding

csar
csar used Ask the Experts™
on
Somebody told me that it is possible to resolve a method statically:
class One {
 public void doit( ) {}
}

class Two extends One{
 public void doit() {}
}

...
One one = new Two();
one.doit(); -- calls Two.doit()

I like to have something like a static_cast in C++ so that I am able to call the method of the super-class.

In C++ terminology all java methods are "virtual". Is it possible to define non-virtual methods in Java?

Maybe a related problem:
Is it possible to dispatch a call to the super-class:
class Two extends One{
 public void doit() {
  super.doit(); -- calls method in super-class
}
}

...works fine, but is it possible to specify the implementing class directly, say One::doit()?

I came across these problems on porting a C++ application to Java. I circumvented these problems, but I am simply curious if it is possible in Java, too

Comment
Watch Question

Do more with

Expert Office
EXPERT OFFICE® is a registered trademark of EXPERTS EXCHANGE®
Ovi

Commented:
I believe you can do'it only in this maneer :

public class test {
  public static void main(String[] args) {
    One one = new Two();
    one.doit();
    try {
      One one1 = (One) one.getClass().getSuperclass().newInstance();
      one.getClass().getSuperclass().getMethod("doit", null).invoke(one1, null);
    } catch(Exception e) { e.printStackTrace(); }
  }

  static class One {
    public void doit() {
      System.out.println("Called from One");
    }
  }

  static class Two extends One {
    public void doit() {
      System.out.println("Called from Two");
    }
  }
}

You can create a special class which can implement this behaviour to simplify the logic and not to live too many dirt in your code. The special class should receive a class Object and a method, lookup after the method in the class of the received object, if founded get it's superclass, lookup in tis too and invoke the method.

The solution could be quiet elegant if you accept to put your hands on the reflection package (java.lang.reflect).

Author

Commented:
Yeah, my example was VERY MUCH simplified. The real situation is that I have a very deep inheritance (root is abstract!). So I cannot create an instance of the root and call the method on it.

I am looking for something in the language definition that I failed to notice sofar. I am just in my third year of Java (no I am not a student!)...

It seems to be tricky, if not impossible. I'll prepare a more elaborated extract from the original problem in th next few days unless somebody knows the (positive/negative) answer.

Commented:
> I like to have something like a static_cast in C++ so that I am able to call the method of the super-class.

> In C++ terminology all java methods are "virtual". Is it possible to define non-virtual methods in Java?

It certainly is. You can define static methods in Java. I'll take your example and modify it to use static methods:

class One {
public static void doit( ) {}
}

class Two extends One{
public static void doit() {}
}

...
One one = new Two();
one.doit(); -- this now calls One.doit(), since one is an instance of One.

You can still call the static method in Two by type casting one like this:
((Two)one).doit(); -- will call Two.doit()

In case you don't already know: you don't even have to instantiate an object to invoke its static methods. For example,

One.doit(); will call static method doit() in One
Two.doit(); will call static method doit() in Two

Now I'd need to know the extact problem you're trying to solve, but if you don't want static methods for some reason you can use reflection like Ovi described it.

The related problem:
> ...works fine, but is it possible to specify the
> implementing class directly, say One::doit()?

Without using reflection, it's not possible. You have to use super if you want to invoke a superclass method inside an overriding method, and it only goes up one class in the inheritance chain (i.e. super.super.<methodName> won't work).
Learn SQL Server Core 2016

This course will introduce you to SQL Server Core 2016, as well as teach you about SSMS, data tools, installation, server configuration, using Management Studio, and writing and executing queries.

Author

Commented:
I know that static methods behave differently so that
one.staticDoit() will call the method staticDoit() defined in the class that "one" was declared from.

This is lexical binding. Note that neither One or Two are singletons. In fact the original problem posed a ListOfOne (Oh I miss C++ Templates, just for saving these casts after getting something out of a collection).

Each element of the list was then asked to return a description of its state and thereby disregarding the information specific to the subclasses. The method called needs access to the member of the instance, so it cannot be a static method.

I tried to "wrap" the static method by calling it from a new method
wrapDoit() {
 staticDoit(this);
}
with
static staticDoit(One one) {
   one.something();
}
defined in all classes, but this doesn't work, since here also the lexical binding applies: wrapDoit() will call staticDoit() of the same class.

Commented:
csar

you can do what you want with Java reflection. check ovi's example
Hi,

There are no non-virtual instance methods in Java. Even reflection sample by Ovi would call subclass method through superclass Method instance. I would suggest to use different mathod in case you don't need subclass version. You also can declare your method final so subclasses won't be able to override it.

public class Super{
    public String superInfo(){
        return "super";
    }
   
    public String overridableInfo(){
        return superInfo();
    }
}

public class Derived extends Super{
    public String overridableInfo(){
        return super.overridableInfo()+" & derived";
    }
}
 

public class Client{
    public String preciseInfo(Super provider){
        return provider.overridableInfo();
    }
    public String baseInfo(Super provider){
        return provider.superInfo();
    }
}

Regards,
Igor Bazarny

Commented:
> There are no non-virtual instance methods in Java. Even reflection sample by Ovi would call subclass method through superclass Method instance.

I did not have time to check Ovi's code, but you can certainly call the some method on some specific class. Swing  L&F implemntation uses similar approach

public static ComponentUI createUI(JComponent x)
Yes, you can do it with static method, but with instance method you are out of luck. I didn't check Ovi code this time, but last time I tried something similar I noted that subclass method was xalled through the superclass reflect.Method instance

Commented:
well the question is about "static binding" :)

Author

Commented:
@bazarny:
You are right about calling via Method:
    try
    {
      Method doit=Class.forName("mypackage6.One").getDeclaredMethod("doit",null);
      doit.invoke(one,null);  
    } catch(Exception ex)
    {
      ex.printStackTrace();
    }

Still calls Two.doit()...

Anyway, don't waste too much time with fancy code here:
1. I solved the problem by redesigning the classes properly (more than a year ago!)
2. The question was meant to be about java syntax. I just want to know if non-virtual methods and/or static bindings are possible in Java. I am fully aware the most usages of these features are a consequence of poor design.

Regards,
  Carsten
The only case you have slight control on instance method called is super.method() construct. In all other cases java language/runtime doesn't let you to choose which version of overridden method to call. It might be possible on bytocode level, but I don't know a way to call superclass method from outside of subclass code. I came from the C++ camp long ago and also was curious. Java lacks losts of C++ funny features and it turns out to be a good thing most of the time.
Ovi

Commented:
For bazarny : congrats for the points ... but anyway as a future suggestion for you : Before you say the code posted by someone in a comment/answear does not produce the expected result please try'it first, you'll be amazed what it can really do. You can pay attention to the next lines :

    One one1 = (One) one.getClass().getSuperclass().newInstance();
     one.getClass().getSuperclass().getMethod("doit", null).invoke(one1, null);
P.S.: I'm not mad as probably seems from the comment :)


In the matter of the question I remain at the same opinion : REFLECTION and "The solution could be implemented quiet elegant if you accept to put your hands on the reflection package (java.lang.reflect)."

If csar is interested in solving the problem, he can implement with few costs (temporal and hard thinking) a framework for handling such problems using reflection (he can read programatically the names of the methods, parameters of the methods, constructors, parameters of the constructors, bla, bla, bla).


Regards to all !
Ovi

Commented:
My "delayed binding" to the question was just because I usually sleep in the night :).

Author

Commented:
Sorry Ovi. This was my first question here. I thought it was possible to split points. You both have deserved them.

I promise to keep this in mind for the case their will be again a photo finish between you two on a question of mine. Then I'll give you the nod.

Your code is fine and I am fully aware of what it is doing:
- create a new instance of One: Problem: One might be abstract
- Find the superclass method doit and invoke it on the new instance. Obviously this executes One.doit() since it is invoked on the new instance. Problem: One is not necessarily the superclass of my instance.

The later can be circumvented (see my code above), but the problem of cloning remains. My first solution the the given real world problem was to implement "copy constructor" One one1 = new One(one) that created a sliced copy of my original object. one1.doit() performed then as expected. This leads to the same result as your code, although in a less elegant manner. Of course I had to dump this approach as the matter came to abstract classes.

Anyway, the original question (see my last remark) was about java syntax.  
Ovi

Commented:
Hi there. I'm not mad at all!!! I've considered the absence of a syntactic solution for your problem as implicit answear in all my comments, since I've posted code to substitute'it ....
There is no need for spliting points, just good luck.

See you all again!
Ovi,

I'm sorry I didn't carefully read your answer. I would have been more clear in my explanation. Yes, your code calls superclass method, but unfortunately for instance which is defferent to one I supposed it should be called for. Well, enough on that. If you wish, I can compensate you points. I've collected some question points and don't really have use for them.

Regards,
Igor Bazarny,
Brainbench MVP for Java 1
Ovi

Commented:
No problem, and no points needed.

See you around :)

Do more with

Expert Office
Submit tech questions to Ask the Experts™ at any time to receive solutions, advice, and new ideas from leading industry professionals.

Start 7-Day Free Trial