public class A {
public void f1(String str) {
System.out.println("A.f1(String)");
this.f1(1, str);
}
public void f1(int i, String str) {
System.out.println("A.f1(int, String)");
}
}
public class B extends A {
#Override
public void f1(String str) {
System.out.println("B.f1(String)");
super.f1(str);
}
#Override
public void f1(int i, String str) {
System.out.println("B.f1(int, String)");
super.f1(i, str);
}
}
public class Main {
public static void main(String[] args) {
B b = new B();
b.f1("Hello");
}
}
I'm seeking that this code would output:
B.f1(String)
A.f1(String)
A.f1(int, String)
Yet I'm getting:
B.f1(String)
A.f1(String)
B.f1(int, String)
A.f1(int, String)
I understand that under the context of B "this" in A.f1(String) is B's instance.
Do I have the option to do the chain new B1().f1(String) -> (A's) f1(String) -> (A's) f1(int, String) ?
This is a theoretical question, practically the solution would obviously be in A to implement a private function that both f1(String) and f1(int, String) would call.
Thank you,
Maxim.
Unfortunately, no
As i'm sure you're aware, but I'll state explicitly for completeness - there are only the 2 keywords to control the method invocation:
this - this.method() - looks for method starting from the invoking instance's class (the instance's "top" virtual table - implied default)
super - super.method() - looks for method starting from the parent class of the class in which the invoking method is defined (the invoking class' parent's virtual table - not strictly true, but simpler to think of this way - thanks #maaartinus)
I can imagine another keyword (e.g. current?) do what you describe:
current - current.method() - looks for method starting from the class in which the invoking method is defined
but Java doesn't have such a keyword (yet?).
I'm afraid, it's impossible, but there's a simple workaround:
public class A {
public void f1(String str) {
System.out.println("A.f1(String)");
privateF1(1, str);
}
private void privateF1(int i, String str) {
System.out.println("A.f1(int, String)");
}
public void f1(int i, String str) {
privateF1(i, str);
}
}
Overridden methods in Java are dynamically bound. i.e. the type of the actual instance of the object dictates what will be called. final methods (which can't be overridden) and private methods (which can't be inherited) are statically bound.
In C++, for contrast, you'd have to explicitly make the functions virtual to get the same behaviour.
package main;
public class A {
public void f1(String str) {
System.out.println("A.f1(String)");
if (this instanceof B)
new A().f1(1, str);
else
this.f1(1, str);
}
public void f1(int i, String str) {
System.out.println("A.f1(int, String)");
}
}
class B extends A {
#Override
public void f1(String str) {
System.out.println("B.f1(String)");
super.f1(str);
}
#Override
public void f1(int i, String str) {
System.out.println("B.f1(int, String)");
super.f1(i, str);
}
public static void main(String[] args) {
A a = new B();
a.f1("Hello");
}
}
Related
public class A {
public void f1(String str) {
System.out.println("A.f1(String)");
this.f1(1, str);
}
public void f1(int i, String str) {
System.out.println("A.f1(int, String)");
}
}
public class B extends A {
#Override
public void f1(String str) {
System.out.println("B.f1(String)");
super.f1(str);
}
#Override
public void f1(int i, String str) {
System.out.println("B.f1(int, String)");
super.f1(i, str);
}
}
public class Main {
public static void main(String[] args) {
B b = new B();
b.f1("Hello");
}
}
I'm seeking that this code would output:
B.f1(String)
A.f1(String)
A.f1(int, String)
Yet I'm getting:
B.f1(String)
A.f1(String)
B.f1(int, String)
A.f1(int, String)
I understand that under the context of B "this" in A.f1(String) is B's instance.
Do I have the option to do the chain new B1().f1(String) -> (A's) f1(String) -> (A's) f1(int, String) ?
This is a theoretical question, practically the solution would obviously be in A to implement a private function that both f1(String) and f1(int, String) would call.
Thank you,
Maxim.
Unfortunately, no
As i'm sure you're aware, but I'll state explicitly for completeness - there are only the 2 keywords to control the method invocation:
this - this.method() - looks for method starting from the invoking instance's class (the instance's "top" virtual table - implied default)
super - super.method() - looks for method starting from the parent class of the class in which the invoking method is defined (the invoking class' parent's virtual table - not strictly true, but simpler to think of this way - thanks #maaartinus)
I can imagine another keyword (e.g. current?) do what you describe:
current - current.method() - looks for method starting from the class in which the invoking method is defined
but Java doesn't have such a keyword (yet?).
I'm afraid, it's impossible, but there's a simple workaround:
public class A {
public void f1(String str) {
System.out.println("A.f1(String)");
privateF1(1, str);
}
private void privateF1(int i, String str) {
System.out.println("A.f1(int, String)");
}
public void f1(int i, String str) {
privateF1(i, str);
}
}
Overridden methods in Java are dynamically bound. i.e. the type of the actual instance of the object dictates what will be called. final methods (which can't be overridden) and private methods (which can't be inherited) are statically bound.
In C++, for contrast, you'd have to explicitly make the functions virtual to get the same behaviour.
package main;
public class A {
public void f1(String str) {
System.out.println("A.f1(String)");
if (this instanceof B)
new A().f1(1, str);
else
this.f1(1, str);
}
public void f1(int i, String str) {
System.out.println("A.f1(int, String)");
}
}
class B extends A {
#Override
public void f1(String str) {
System.out.println("B.f1(String)");
super.f1(str);
}
#Override
public void f1(int i, String str) {
System.out.println("B.f1(int, String)");
super.f1(i, str);
}
public static void main(String[] args) {
A a = new B();
a.f1("Hello");
}
}
In java, I'd like to do something like this
public class Tata{
public static void f(){
//something
}
public static void g(){
//something
}
}
public class Titi{
public static void f(){
//something
}
public static void g(){
//something
}
}
public class Toto{
private Class c = Tata.class; //or Titi.class
public static void main(String[] args) {
c.f();
c.g();
}
}
To be precise, I'd like to be able to freely switch between classes Tata and Titi, to use their respective methods f or g.
This doesn't work as intended, as I get the cannot resolve method 'f()' error. Simply replacing c.f(); and c.g(); with Tata.f(); and Tata.g(); works fine, but defeats the purpose of using a parameter. How to solve this?
Will turn the comment into answer after all.. The correct (Java) way to deal with what you want is the use of interface. So in your demo code the implementation would be the following:
public interface TheFGFunctions {
void f();
void g();
}
public class Tata implements TheFGFunctions {
#Override
public void f() {
//something
}
#Override
public void g() {
//something
}
}
public class Titi implements TheFGFunctions {
#Override
public void f() {
//something
}
#Override
public void g() {
//something
}
}
public class Toto {
private TheFGFunctions c;
public Toto(TheFGFunctions c) {
this.c = c;
}
public void notStaticFunction() {
c.f();
c.g();
}
}
This way is totally typesafe with zero exceptions to deal with!
You cannot access a static method polymorphically. The Java language doesn't support it.
The reason your current approach fails is that c is an instance of the class Class, and the class Class doesn't define methods f() or g().
(The methods that it does define are listed in the javadoc for Class. Note that Class is final so you can't create a custom subclass with extra methods.)
The simple alternative is to use reflection; e.g.
Class c =
Method f = c.getMethod("f");
f.invoke(null); // because it is static
But note:
This is not statically type-safe. The compiler cannot tell when you make the mistake of trying to use a static f() on a class that doesn't have such a method.
There are a few exceptions that you need to deal with; e.g. missing methods, incorrect signatures, methods that are not static, methods that don't have the correct access.
Other answers have proposed creating an interface and wrapper classes to make certain static methods dispatchable. It will work and it will be compile-time type-safe (!) but there is a lot of boiler plate code to write.
#Michael Michailidis commented:
Thus interfaces!
Yea ... kind of. You can only dispatch polymorphically on instance methods declared on an interface. That implies that you must have an instance of Tata or Titi, and call the methods on it. My reading of the Question is that the author wants to avoid that.
(IMO, the avoidance is the real problem. You are better of not trying to avoid instance methods.)
FWIW, you can declare static methods in an interface (since Java 8), but they would behave the same as if you declared them in a class. You wouldn't be able to dispatch ...
You could use reflections:
private Class c = Tata.class;
public Toto() throws Exception {
c.getMethod("f").invoke(null);
c.getMethod("g").invoke(null);
}
Here my Tata class
public class Tata {
public static void f() {
System.out.println("ffff");
}
public static void g() {
System.out.println("gggg");
}
}
Output on new Toto() call:
ffff
gggg
Update (call with parameters):
public Toto() throws Exception {
c.getMethod("f", String.class).invoke(null, "paramValue1");
c.getMethod("g", String.class).invoke(null, "paramValue2");
}
public class Tata {
public static void f(String param1) {
System.out.println("ffff " + param1);
}
public static void g(String param2) {
System.out.println("gggg " + param2);
}
}
Output:
ffff paramValue1
gggg paramValue2
Write a wrapper interface
interface CWrapper {
void f();
void g();
}
and wrapper class factory method for each Class containing the methods
class CWrappers {
CWrapper forTiti(Class<Titi> titiClass) {
return new CWrapper() {
void f() { Titi.f(); }
void g() { Titi.g(); }
}
}
// another factory method for Tata
}
Then you can use that:
public class Toto {
private CWrapper c = CWrappers.forTata(Tata.class); //or forTiti(Titi.class)
public static void main(String[] args) {
c.f();
c.g();
}
}
Is it possible to overload Enum abstract method?
I have tried this in my code with no effect.
Presented class
public class Test {
public void test(String string){
System.out.println(string);
}
public void test(Object object){
System.out.println("Test1");
}
public static void main(String[] args) {
Object object = new Object();
test.test(object);
test.test("what if?");
}
}
gives expected result of
Test1
what if?
while enum
public enum TestEnum {
TEST1{
public void test(String string){
System.out.println(string);
}
public void test(Object object){
System.out.println("Test1");
}
},
TEST2{
public void test(Object object){
System.out.println("Test2");
}
};
public abstract void test(Object object);
}
public class Test {
public static void main(String[] args) {
Object object = new Object();
TestEnum.TEST1.test("what if?");
TestEnum.TEST1.test(object);
}
}
returns
Test1
Test1
Is it even possible to overload Enum methods or am I doing something wrong? Or maybe should I check for type inside of overriden method and then act accordingly? But then I remove switch statement only to introduce another switch statement.
The thing about enums is that values with bodies are implemented as anonymous subclasses of TestEnum; so they look like this:
final TestEnum TEST1 = new TestEnum() { /* body */ };
Whilst the concrete class of TEST1 is, say TestEnum$1 (or whatever name the compiler decides to give it), the reference is of type TestEnum, so any code outside the body of TEST1 can only access methods defined on TestEnum.
Yes is possible, you are somehow not implementing that in a particular way....
you should
define an interface with the methods you want to override
interface Ifoo {
public void test(Object object);
public void test(String object);
}
then remove the abstract method of the enum and make the enum implement that interface, but override those methods in every constant of the enumerator...
enum TestEnum implements Ifoo {
TEST1 {
#Override
public void test(String string) {
System.out.println(string);
}
#Override
public void test(Object object) {
System.out.println("Test1");
}
},
TEST2 {
#Override
public void test(Object object) {
System.out.println("Test2");
}
#Override
public void test(String string) {
System.out.println(string);
}
};
}
finally implement it like>
Object object = new Object();
TestEnum.TEST1.test("what if?");
TestEnum.TEST1.test(object);
TestEnum.TEST2.test("why not?");
TestEnum.TEST2.test(object);
your result should looks like:
what if?
Test1
why not?
Test2
You are showing an example with a class and then you are showing an example with an enum. I believe you think these examples are equivalent, however, they are completely different each other.
For the example of your class to be equivalent to the example of your enum, you should modify your Test class so that it extends an abstract AbstractTest class:
public abstract class AbstractTest {
public abstract void test(Object object);
}
public class Test extends AbstractTest {
public void test(String string) {
System.out.println(string);
}
#Override
public void test(Object object) {
System.out.println("Test1");
}
}
Now, if you try the same lines you've tried in your first main:
AbstractTest test = new Test();
Object object = new Object();
test.test(object);
test.test("what if?");
You'll notice that the output has now become:
Test1
Test1
Which is something to be expected, because Java doesn't provide a feature called dynamic dispatch. Informally, dynamic dispatch means that the overloaded method to be executed is decided at runtime, based on the polymorphic types of the parameters. Instead, Java decides the method to be executed at compilation time, based on the declared type of the object whose method is to be invoked (in this case AbstractTest).
With enums, this is exactly what happens. All the elements of the enum (TEST1 and TEST2 in your example) belong to the type of the enum (TestEnum in your case), so the compiler always goes for the method that is declared as abstract.
The reason why you get twice "Test1" is because you have declared only this method
public abstract void test(Object object);
Precisely, this method will "catch" all calls whit any type of parameter. String extends Object (indirectly), so String is Object and this method we be called.
In other words, method wich receives parameter String will be hidden by the method which receives parameter Object.
The solution is to add next method declaration in enum
public abstract void test(String string);
You will have to add the implementation of this method to TEST2 constant.
Code
public enum TestEnum {
TEST1 {
public void test(String string) {
System.out.println(string);
}
public void test(Object object) {
System.out.println("Test1");
}
},
TEST2 {
public void test(Object object) {
System.out.println("Test2");
}
#Override
public void test(String string) {
// TODO Auto-generated method stub
}
};
public abstract void test(Object object);
public abstract void test(String string);
}
This code gives output
what if?
Test1
I have a Functional Interface in the code below which has one abstract method and one object method override. So when I write Lambda expression for that , how can I implement my equals method.
import static java.lang.System.out;
public class Test {
public static void main(String[] args) {
AddToString test = a -> (a + " End");
out.println(test.stringManipulation("some string"));
out.println(test.increment(5));
out.println(test.equals(null));
}
}
#FunctionalInterface
interface AddToString {
String stringManipulation(String a);
default int increment(int a) { return a+1; }
#Override
public boolean equals(Object obj);
}
One way to do that is to create Anonymous class like given below, but is there a better method using lambda expressions -
public class Test {
public static void main(String[] args) {
AddToString test = new AddToString() {
public String stringManipulation(String a) {
return a + " End";
}
#Override
public boolean equals(Object Obj) {
//Just testing whether it overrides
return 5==5;
}
};
out.println(test.stringManipulation("some string"));
out.println(test.increment(5));
out.println(test.equals(null));
}
}
You can't. If you need to override equals, you'll need to create a class (anonymous or otherwise), you can't do it with a lambda.
Let us say I have following overloaded functions
public class Test {
public static void funOne(String s){
System.out.print("String function");
}
public static void funOne(Object o){
System.out.print("Object function");
}
public static void main(String[] args) {
funOne(null);
}
}
Why would funOne(null) call the method with String argument signature? what is the precedence for overloading here?
The class that is lower in the class hierarchy will have precedence in this case. In other words the more specific class type, which would be String in this case because String extends Object technically.
If you have the following
public class A {
...
}
public class B extends A {
...
}
Then when you define overloading methods like the following:
public void test(A object) {
...
}
public void test(B object) {
...
}
Then calling test(null) will call the second method because B is lower in the class hierarchy.
Your question is more fully answered here with references.
Also, you can force a particular method to be called by doing this:
funOne((Object) null);