Overload enum abstract method - java

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

Related

How to properly use a parameter of type class?

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();
}
}

Can I use default method in is override? [duplicate]

Java 8 introduces default methods to provide the ability to extend interfaces without the need to modify existing implementations.
I wonder if it's possible to explicitly invoke the default implementation of a method when that method has been overridden or is not available because of conflicting default implementations in different interfaces.
interface A {
default void foo() {
System.out.println("A.foo");
}
}
class B implements A {
#Override
public void foo() {
System.out.println("B.foo");
}
public void afoo() {
// how to invoke A.foo() here?
}
}
Considering the code above, how would you call A.foo() from a method of class B?
As per this article you access default method in interface A using
A.super.foo();
This could be used as follows (assuming interfaces A and C both have default methods foo())
public class ChildClass implements A, C {
#Override
public void foo() {
//you could completely override the default implementations
doSomethingElse();
//or manage conflicts between the same method foo() in both A and C
A.super.foo();
}
public void bah() {
A.super.foo(); //original foo() from A accessed
C.super.foo(); //original foo() from C accessed
}
}
A and C can both have .foo() methods and the specific default implementation can be chosen or you can use one (or both) as part of your new foo() method. You can also use the same syntax to access the default versions in other methods in your implementing class.
Formal description of the method invocation syntax can be found in the chapter 15 of the JLS.
This answer is written mainly for users who are coming from question 45047550 which is closed.
Java 8 interfaces introduce some aspects of multiple inheritance. Default methods have an implemented function body. To call a method from the super class you can use the keyword super, but if you want to make this with a super interface it's required to name it explicitly.
class ParentClass {
public void hello() {
System.out.println("Hello ParentClass!");
}
}
interface InterfaceFoo {
public default void hello() {
System.out.println("Hello InterfaceFoo!");
}
}
interface InterfaceBar {
public default void hello() {
System.out.println("Hello InterfaceBar!");
}
}
public class Example extends ParentClass implements InterfaceFoo, InterfaceBar {
public void hello() {
super.hello(); // (note: ParentClass.super could not be used)
InterfaceFoo.super.hello();
InterfaceBar.super.hello();
}
public static void main(String[] args) {
new Example().hello();
}
}
Output:
Hello ParentClass!
Hello InterfaceFoo!
Hello InterfaceBar!
The code below should work.
public class B implements A {
#Override
public void foo() {
System.out.println("B.foo");
}
void aFoo() {
A.super.foo();
}
public static void main(String[] args) {
B b = new B();
b.foo();
b.aFoo();
}
}
interface A {
default void foo() {
System.out.println("A.foo");
}
}
Output:
B.foo
A.foo
You don't need to override the default method of an interface. Just call it like the following:
public class B implements A {
#Override
public void foo() {
System.out.println("B.foo");
}
public void afoo() {
A.super.foo();
}
public static void main(String[] args) {
B b=new B();
b.afoo();
}
}
Output:
A.foo
It depends on your choice whether you want to override the default method of an interface or not. Because default are similar to instance method of a class which can be directly called upon the implementing class object. (In short default method of an interface is inherited by implementing class)
Consider the following example:
interface I{
default void print(){
System.out.println("Interface");
}
}
abstract class Abs{
public void print(){
System.out.println("Abstract");
}
}
public class Test extends Abs implements I{
public static void main(String[] args) throws ExecutionException, InterruptedException
{
Test t = new Test();
t.print();// calls Abstract's print method and How to call interface's defaut method?
}
}

A sorta extentsion on a method java

So i'm creating a API to java and i need a extention like thing on my method. Example:
someMethod().getName();
Something like that. Anyone know how?
What you are trying to do is something called method chaining. Let's put this example:
obj.methodOne().methodTwo()
This will call methodTwo() from the object returned by the call obj.methodOne(), so you can think the above chain as if it were this:
(obj.methodOne()).methodTwo()
Let's say you have this class:
public class MyClass2 {
public int methodTwo() {...}
}
Then, to be able to call methodTwo from the result of obj.methodOne(), the method methodOne() should return an instance of the class MyClass2:
public class MyClass1 {
public MyClass2 methodOne() {
return new MyClass2(); // returns instance of 'MyClass2'
}
}
Not sure what you mean, but this may help
class Foo {
Object someMethod() {
...
return new Object() {
public String toString() {
return "Bar";
}
}
}
}
What you're doing is returning an anonymous class and that overrides toString().
You can read more about anonymous classes here: http://docs.oracle.com/javase/tutorial/java/javaOO/anonymousclasses.html
I think you are unable to express your question.
1) If you want to have toString() method in a class you can do the following:
public class XYZ
{
//Your properties and methods
#Override
public String toString()
{
//Manipulate what you want to return as a String
return a_string;
}
}
2) You want to call a method on the result of a method. Method Chaining
class XYZ
{
//Your properties and methods
public ABC getABC()
{
return an_ABC_object;
}
}
class ABC
{
public void doSomething()
{
// do some work or print something
}
}
public class Test
{
public static void main(String arg[])
{
XYZ xyz=new XYZ();
xyz.getABC().doSomething();
}
}

Calling overloaded functions with "null" reference

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);

Super class which uses the values from children

I wanted to implement a method in a abstract class that is called by the inherited classes and uses their values.
For instance:
abstract class MyClass{
String value = "myClass";
void foo(){System.out.println(this.value);}
}
public class childClass{
String value="childClass";
void foo(){super.foo();}
}
public static void main(String[] args){
new childClass.foo();
}
This will output "myClass" but what I really want is to output "childClass". This is so I can implement a "general" method in a class that when extended by other classes it will use the values from those classes.
I could pass the values as function arguments but I wanted to know if it would be possible to implement the "architecture" I've described.
A super method called by the inherited class which uses the values from the caller not itself, this without passing the values by arguments.
You could do something like this:
abstract class MyClass {
protected String myValue() {
return "MyClass";
}
final void foo() {
System.out.println(myValue());
}
}
public class ChildClass extends MyClass {
#Override
protected String myValue() {
return "ChildClass";
}
}
and so on
This is a place where composition is better than inheritance
public class Doer{
private Doee doee;
public Doer(Doee doee){
this.doee = doee;
}
public void foo(){
System.out.println(doee.value);
}
}
public abstract class Doee{
public String value="myClass"
}
public ChildDoee extends Doee{
public String= "childClass"
}
...
//Excerpt from factory
new Doer(new ChildDoee);
I believe you are asking whether this is possible:
public class MyClass {
void foo() {
if (this instanceof childClass) // do stuff for childClass
else if (this intanceof anotherChildClass) // do stuff for that one
}
}
So the answer is "yes, it's doable", but very much advised against as it a) tries to reimplement polymorphism instead of using it and b) violates the separation between abstract and concrete classes.
You simply want value in MyClass to be different for an instance of childClass.
To do this, change the value in the childClass constructor:
public class childClass {
public childClass() {
value = "childClass";
}
}
Edited:
If you can't override/replace the constructor(s), add an instance block (which gets executed after the constructor, even an undeclared "default" constructor):
public class childClass {
{
value = "childClass";
}
}

Categories