Abstract overload method
Is it possible to overload an abstract Enum method?
I've tried this in my code with no effect. Introduced 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 the expected result
Test1
what if?
while the enumeration
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 the Enum methods or am I doing something wrong? Or maybe I should check the type inside the overriden method and then act accordingly? But then I remove the switch statement just to introduce another switch statement.
source to share
The point about enums is that values ββwith bodies are implemented as anonymous subclasses TestEnum
; so they look like this:
final TestEnum TEST1 = new TestEnum() { /* body */ };
While a particular class TEST1
is, say, TestEnum$1
(or whatever name the compiler decides to give), the reference is of type TestEnum
, so any code outside the body TEST1
can only access the accessor methods defined in TestEnum
.
source to share
Yes, you may not be implementing this in a certain way somehow ....
you must 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 enumeration method and make enum implement that interface, but override those methods in every enumerator constant ...
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 look like this:
what if?
Test1
why not?
Test2
source to share
You show an example with a class, and then you show an example with an enum. I believe you think these examples are equivalent, however they are completely different.
For your class example to be equivalent to your enum example, you should modify your class Test
to extend the abstract class AbstractTest
:
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 tried in your first one main
:
AbstractTest test = new Test();
Object object = new Object();
test.test(object);
test.test("what if?");
You will notice that the result is now:
Test1
Test1
Which can be expected because Java does not provide a dynamic mailing feature . Informally, dynamic dispatch means that the overloaded method to be executed is determined at runtime based on the polymorphic types of the parameters. Instead, Java decides the method to be executed at compile time based on the declared type of the object whose method is to be called (in this case AbstractTest
).
With enums, this is exactly what happens. All elements of an enum ( TEST1
and TEST2
in your example) are of an enum type ( TestEnum
in your case), so the compiler always goes for a method declared as abstract.
source to share
The reason you get "Test1" twice is because you only declared this method. public abstract void test(Object object);
This method will "catch" all calls with any parameter type. String extends Object (indirectly), so String is Object and we will call this method.
In other words, the method that receives the String parameter will be hidden by the method that receives the Object parameter.
The solution is to add the following method declaration to the enum. public abstract void test(String string);
You will need to add the implementation of this method to the constant TEST2
.
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 outputs
what if?
Test1
source to share