How to call Enum individual methods? - java

I have an enum that might look like the one below. My goal is to have an enum with some common methods (I enforced this by adding an abstract method) and some "enum value individual" methods.
The following code compiles:
public enum MyEnum {
VALUE {
#Override
public void syso() {
System.out.println("VALUE syso");
}
},
SPECIAL_VALUE {
#Override
public void syso() {
System.out.println("SPECIAL_VALUE syso");
}
public void sayHello() {
System.out.println("Hello");
}
};
public abstract void syso();
public static void main(String... args) {
MyEnum.VALUE.syso();
MyEnum.SPECIAL_VALUE.syso();
}
}
Running this results in the following being printed:
VALUE syso
SPECIAL_VALUE syso
However trying to call sayHello(), which I defined in SPECIAL_VALUE, does not work.
Adding the following to the main method, does not compile anymore:
public static void main(String... args) {
MyEnum.SPECIAL_VALUE.sayHello(); // does not work
}
Why is that? It seems perfectly fine to me, but the method cannot be found. Is there any way to invoke this method? Maybe via reflection?
I would like to avoid making this method abstract as well, because it does not make sense for any other enum values. I also cannot extend this enum and add this special method, while inheriting the common ones. I would also like to avoid adding some kind of singleton class to "simulate" this.
Is it anyhow possible to run this? If not, what would be my best alternative?

Why is that?
The reason is given in the JLS:
8.9.1. Enum Constants
...
Instance methods declared in enum class bodies may be invoked outside the enclosing enum type only if they override accessible methods in the enclosing enum type (§8.4.8).
Is there any way to invoke this method? Maybe via reflection?
Given the above constraint, reflection is the only alternative if you do not want to expose the method in the enclosing enum class. Each enum constant is created as an inner class, like MyEnum$1 and MyEnum$2 in your example. Thus, you can retrieve the Class through the constant's getClass() method and then call your method through reflection (exception handling omitted):
...
Class c = MyEnum.SPECIAL_VALUE.getClass();
Method m = c.getMethod("sayHello");
m.invoke(MyEnum.SPECIAL_VALUE);
...
I would most likely try to avoid reflection and expose the method in the enum class, and let it throw an UnsupportedOperationException:
...
public void sayHello() {
throw new UnsupportedOperationException();
}
...
This at least catches unintended calls during runtime - it still does not allow the compiler to catch them during compile time, but neither does the reflection approach.

Because SPECIAL_VALUE is an instance of enum and enum has only method syso().you are calling
Here is the same thing with classes:
interface Foo {
Foo inst1 = new Foo() {
#Override
public void doFoo() {
}
public void doAnonymous() {
}
};
void doFoo();
}
You cannot call method doAnonymous() like Foo.inst1.doAnonymous() and you are able to access the doAnonymous only via reflection

Related

Enum implementing interface, interface and method visibility

I just came accross the following code, which surprised me a little bit, I converted it to a simple SSCEE here though:
custompackage.package1.MyEnum.java
public enum MyEnum implements MyInterface {
CONSTANT_ONE() {
#Override
public void myMethod() {
//do something very interesting
}
},
CONSTANT_TWO() {
#Override
public void myMethod() {
//do something very interesting
}
};
}
interface MyInterface {
void myMethod();
}
Now from outside this package, I can do the following:
Consumer<MyEnum> myMethod = MyEnum::myMethod;
However I am not able to use MyInterface at all, which I understand as it is package-private to custompackage.package1.
I don't understand what exactly is going on though, it seems like MyEnum got the myMethod() method added, but it does not implement (from the outside) MyInterface.
How does this work?
Well you can't see MyInterface from outside the package, as you said - but MyEnum effectively has a public abstract myMethod() method, which you're able to use as a method reference.
Leaving aside fancy new Java 8 features, this is valid (even outside the package):
// Even MyEnum x = null; will compile, but obviously fail
MyEnum x = MyEnum.CONSTANT_ONE;
x.myMethod();
The method is inherited from the interface, even though the interface itself is not visible.
This isn't specific to interfaces and enums, either. For example:
// Foo.java
package foo;
class SuperFoo {
public void publicMethod() {
}
}
public class Foo extends SuperFoo {
}
// Bar.java
package bar;
import foo.Foo;
public class Bar {
public void test() {
Foo foo = new Foo();
foo.publicMethod();
}
}
This compiles fine, even though Foo doesn't even override publicMethod. As far as Bar is concerned, it's inherited from somewhere, but it doesn't know where!
In interfaces methods are public abstract by default. fields are public static final
the reason you can use the method is that the interface is package local. Try making it public.
However I am not able to use MyInterface at all, which I understand as it is package-private to custompackage.package1.
The interface is package-private, but all methods (and fields) are (implicitly or explicit) public.
it seems like MyEnum got the myMethod() method added, but it does not implement (from the outside) MyInterface.
MyEnum has a public method called myMethod(), regardless of whether it inherited the (public) abstract method from the interface or whether it declared the method itself. Said another way, even if the outside cannot see the interface, the outside can certainly see MyEnum and see MyEnum.myMethod().

Can I tell if an abstract method has been called?

Given this class:
abstract class Foo{
public Foo(){...}
public abstract void checkable();
public void calledWhenCheckableIsCalled(){
System.out.println("checkable was called");
}
}
Is there any code I can put in Foo's constructor to make calledWhenCheckableIsCalled get called when checkable is called?
Note: This is a gross simplification of an actual project I am working on.
Edit: I have already implemented a template pattern workaround. I just wondered if there was another way to do this I am missing. (Perhaps using reflection.)
Looks like a template method pattern.
But then you must implement Foo.checkable() and introduce another abstract method to delegate to.
abstract class Foo{
public Foo(){}
public void checkable(){
calledWhenCheckableIsCalled();
doCheckable();
}
protected abstract void doCheckable();
public void calledWhenCheckableIsCalled(){
System.out.println("checkable was called");
}
}
I would also suggest to make checkable() final in this case so that you can be sure that checkable() can not implemented in another way as you expected.
In addition to Brian Roach's comment
The downside is that the protected can be expanded to public in the subclass, so you can't explicitly enforce it.
That's true, but you can prevent a Foo instance from being instantiated if a subclass increases the visibility of doCheckable. Therefore you have to introduce a verification whenever an object is instantiated. I would recommend to use an initializer code so that the verification is executed on every constructor that exists. Then it can not be forgotten to invoke and therefore be by-passed.
For example:
abstract class Foo {
{ // instance initializer code ensures that enforceDoCheckableVisibility
// is invoked for every constructor
enforceDoCheckableVisibility();
}
public Foo() {...}
public Foo(Object o) {...}
private void enforceDoCheckableVisibility() {
Class<?> currentClass = getClass();
while (currentClass != Foo.class) {
try {
Method doCheckableMethod = currentClass.getDeclaredMethod("doCheckable");
if (Modifier.isPublic(doCheckableMethod.getModifiers())) {
throw new RuntimeException("Visibility of "
+ currentClass.getSimpleName()
+ ".doCheckable() must not be public");
}
} catch (SecurityException | NoSuchMethodException e) {}
currentClass = currentClass.getSuperclass();
}
}
}
Since the check is implemented using reflection the downside is that it is only checked at runtime. So you will not have compiler support of course. But this approach let you enforce that an instance of a Foo can only exist if it fulfills your contract.
No, the constructor will get invoked once during the object initialisation. You can however get your subclass that provides the implementation to call the method in the super class:
class Bar extends Foo {
// implementation of abstract method
public void checkable(){
super.calledWhenCheckableIsCalled(); // call to parent's method
...
}
}
EDIT
You could achieve this with aspects. Using an aspect you can intercept each call to a method by referring to the abstract parent method. This leaves you free from interfering eith the child code. Your calledWhenCheckableIsCalled code would then become part of the intercepting code.
abstract class Foo {
// use pointcut to intercept here
public void checkable();
}
There is no way as you are forcing that method to implement in child.
An awkward suggestion will be know from child implementation. I mean there is no clean way AFAIK
abstract class foo {
public abstract void bar();
public void moo() {
System.out.println("some code");
this.bar();
System.out.println("more code");
}
}
now if moo is called, the underlying implementation of bar will be used, it is just a small paradigm shift from what you want.
so your end user would call moo instead of bar, but he still needs to implement bar
Nope, an abstract method doesn't have a body. You could, however, chain your method like this:
abstract class Foo {
void callMeInstead() {
// do common
callMeImplementation();
}
abstract void callMeImplementation();
}
It looks to me like you're looking for the template pattern:
public abstract class Template {
public final void checkable() {
calledWhenCheckableIsCalled();
doCheckable();
}
protected abstract void doCheckable();
private void calledWhenCheckableIsCalled() {
System.out.println("checkable was called");
}
}
Now, each time checkable() is called, calledWhenCheckableIsCalled() is also called. And the suclass must still provide the actual implementation of checkable(), by implementing the doCheckable() method.
Note that making checkable() final prevents a subclass from overriding it and thus bypassing the call to calledWhenCheckableIsCalled().

Singletons, Enums and anonymous inner classes

As you may know, some people are declaring singletons with an Enum of 1 instance, because the JVM guarantees that there will always be a single instance with no concurrency problems to handle...
Thus what about an Enum with multiple instances?
Can we say something like an Enum is a kind of ordered set of singletons sharing a common interface?
Why?
public enum EnumPriceType {
WITH_TAXES {
#Override
public float getPrice(float input) {
return input*1.20f;
}
public String getFormattedPrice(float input) {
return input*1.20f + " €";
}
},
WITHOUT_TAXES {
#Override
public float getPrice(float input) {
return input;
}
},
;
public abstract float getPrice(float input);
public static void main(String[] args) {
WITH_TAXES.getFormattedPrice(33f);
}
}
In this code why this doesn't work:
WITH_TAXES.getFormattedPrice(33f);
What is the interest of declaring a public method if it can't be called without passing through the common interface?
I guess this is why i don't see any syntax to be able to declare an interface just for one of the instances of an Enum.
Edit:
It seems that enum instances are a special kind of anonymous classes.
Thus i understand why you can't call that method.
My question is kinda related to: why can't an anonymous class implement an interface (in addition to the interface it may already implement!)
I totally understand why we CANT do that:
Vehicle veh = new Vehicle() {
public String getName() {
return "toto";
}
};
veh.getName();
(getName here is not an override)
Why i don't understand is why we can't do that with anonymous classes:
Runnable veh = new Vehicle() implements Runnable {
#Override
public void run() {
System.out.println("i run!");
}
};
veh.run();
Or something that would result in the same thing.
Think about it: if you do not use anonymous classes you can absolutely extend the Vehicle class and then make that subclass implement any other interfaces you want...
I'm pretty sure that if it was possible we would be able to call WITH_TAXES.getFormattedPrice(33f) in a typesafe way, since WITH_TAXES would not be a real EnumPriceType but it would but a subclass of EnumPriceType, with its own interface, and by calling WITH_TAXES.getFormattedPrice(33f) with a hardcoded WITH_TAXES, you know at compile that which EnumPriceType child you are calling.
So my question is: are there any reasons why this is not possible? Or it just haven't be done yet?
Your enum is equivalent to the following normal class (in fact, that's pretty much what the compiler turns it into):
public abstract class EnumPriceType {
public static final EnumPriceType WITH_TAXES = new EnumPriceType() {
//getPrice() {...}
//getFormattedPrice() {...}
};
public static final EnumPriceType WITHOUT_TAXES = new EnumPriceType() {
//getPrice() {...}
};
public abstract float getPrice(float input);
public static void main(String[] args) {
WITH_TAXES.getFormattedPrice(33f);
}
}
The getFormattedPrice() method is unavailable on the abstract type, and therefore can't be called from the main method. Consider what would happen if the main method is rewritten to use a local variable:
public static void main(String[] args) {
EnumPriceType foo = EnumPriceType.WITH_TAXES;
foo.getFormattedPrice(33f);
}
This doesn't compile because getFormattedPrice() is not available on the base class. Since the WITH_TAXES instance is an anonymous subclass of EnumPriceType, there's no way you can define the local variable to a type where the getFormattedPrice() method is visible.
As a meta observation, this is a key difference between strongly typed languages such as Java and "duck typed" languages such as Ruby. Ruby will happily invoke the getFormattedPrice() method if happens to be there, regardless of what type of object is held in the foo variable.
As another meta observation, it doesn't make much sense for different constants of the same enum to have different sets methods. If you can't put everything you need as abstract (or concrete) methods on the base enum type, you're probably using the wrong tool to solve the problem.
Add
public String getFormattedPrice(float input) {
return input + " €";
}
outside the overrides as the default implementation. (Next to the declaration of getPrice.) And you are good to go.
You can also have enums implement interfaces, to define what everybody needs to implement.
Thus what about an Enum with multiple instances?
There is no such thing, and your example doesn't demonstrate it. You have an Enum with multiple values. They are all singletons.

Implicit object type in Java?

This isn't exactly the definition of implicit type conversion, but I'm curious how many standards I'm breaking with this one...
I'm creating an abstract class in Java that basically casts its variables depending on a string passed into the constructor.
For example:
public abstract class MyClass {
Object that;
public MyClass(String input){
if("test1".equals(input){
that = new Test1();
}
else{
that = new Test();
}
}
public void doSomething(){
if(that instanceof Test1){
//specific test1 method or variable
} else if(that instanceof Test2)}
//specific test2 method or variable
} else {
//something horrible happened
}
}
}
You see what I'm getting at? Now the problem I run into is that my compiler wants me to explicitly cast that into Test1 or Test2 in the doSomething method - which I understand, as the compiler won't assume that it's a certain object type even though the if statements pretty much guarantee the type.
I guess what I'm getting at is, is this a valid solution?
I have other classes that all basically do the same thing but use two different libraries depending on a simple difference and figure this class can help me easily track and make changes to all of those other objects.
You are right. This is a horrible way to achieve polymorphism in design. Have you considered using a factory? A strategy object? It sounds like what you are trying to achieve can be implemented in a more loosely-coupled way using a combination of these patterns (and perhaps others).
For the polymorphism of doSomething, for example:
interface Thing {
public void doThing();
}
class Test1 implements Thing {
public void doThing() {
// specific Test1 behavior
}
}
class Test2 implements Thing {
public void doThing() {
// specific Test2 behavior
}
}
class MyClass {
Thing _thing;
public void doSomething() {
_thing.doThing(); // a proper polymorphism will take care of the dispatch,
// effectively eliminating usage of `instanceof`
}
}
Of course, you need to unify the behaviors of Test1 and Test2 (and other concrete Thing classes, present and planned) under a set of common interface(s).
PS: This design is commonly known as Strategy Pattern.
I would create a separate class file. So you would have something like this:
1. You abstract "MyClass"
->within "MyClass" define an abstract method call doSomething...this will force the specific implementation of the method to it's subclasses.
2. Test1 would be the implementation of MyClass which would contain the implementation of the doSomething method
3. Create a utility class that does the check "instanceOf" that check should not be in the constructor it belongs in another class.
So in the end you would have 3 class files an Abstract Class, Implementation of the Abstract and a Class that does the "instanceOf" check. I know this sounds like a lot but it's the proper way to design, for what I think you are attempting to do. You should pick up a design patterns book, I think it would help you a lot with questions like these.
The Open-Closed principle would be better satisfied by moving the object creation outside of this class.
Consider changing the constructor to accept an object that implements an interface.
public MyClass {
public MyClass( ITest tester ) { m_tester = tester; }
public void doSomething(){ m_tester.doTest(); }
}
This makes it possible to change the behavior of the class (open to extension) without modifying its code (closed to modification).
The better way to do this is to create an interface which will specify a set of methods that can be guaranteed to be called on the object.
Here's an example:
public interface TestInterface
{
void doTest();
}
Now you can write your classes to implement this interface. This means that you need to provide a full definition for all methods in the interface, in this case doTest().
public class Test implements TestInterface
{
public void doTest()
{
// do Test-specific stuff
}
}
public class Test1 implements TestInterface
{
public void doTest()
{
// do Test1-specific stuff
}
}
Looks really boring and pointless, right? Lots of extra work, I hear you say.
The true value comes in the calling code...
public abstract class MyObject
{
Test that;
// [...]
public void doSomething()
{
that.doTest();
}
}
No if statements, no instanceof, no ugly blocks, nothing. That's all moved to the class definitions, in the common interface method(s) (again, here that is doTest()).

Does the super class not call the overridden method?

I have the following classes:
class foo {
public void a() {
print("a");
}
public void b() {
a();
}
}
class bar extends foo {
public void a() {
print("overwritten a");
}
}
When I now call bar.b() I want it to call the overridden method a() in foo. It does, however, print "a".
Are your two classes in different packages? And is your foo class methods declared public, protected, or private or package local? Obviously if they are private, this won't work. Perhaps less obvious, is if they are package local (i.e. no public/protected/private scope) then you can only override them if you are in the same package as the original class.
For example:
package original;
public class Foo {
void a() { System.out.println("A"); }
public void b() { a(); }
}
package another;
public class Bar extends original.Foo {
void a() { System.out.println("Overwritten A"); }
}
package another;
public class Program {
public static void main(String[] args) {
Bar bar = new Bar();
bar.b();
}
}
In this case, you will still get 'A'. If you declare the original a() method in Foo public or protected, you will get the result you expected.
It may be that you are trying to use static methods, which won't work as they don't get overridden.
A good way of checking is to add the #Override annotation to bar.a() and see if the compiler gives you an error that a() isn't actually overidding anything
When I run the following:
public class Program {
public static void main(String[] args) {
bar b = new bar();
b.b();
}
}
class foo {
public void a() {
System.out.printf("a");
}
public void b() {
a();
}
}
class bar extends foo {
public void a() {
System.out.printf("overwritten a");
}
}
I get the following output:
overwritten a
which is what I would expect to see.
Are the methods defined as static? That's the only way I could see getting that result. I found a good explanation about that here: http://faq.javaranch.com/view?OverridingVsHiding
You may be confused if you are coming from C# or some other language where you have to explicitly declare virtual functions and/or overriding functions.
In Java, all instance functions are virtual, and can be overridden -- unless they are declared as private and/or final.
It is not necessary to specify the new #Override annotation to do so, adding the annotation just specifies that your intent is to override, and will cause a either a warning or error if it isn't an override. (If you accidentally misspelled the method name for example).
Andrew's example shows how this should work.
From the horse's mouth:
http://download.oracle.com/javase/tutorial/java/IandI/override.html
"The version of the overridden method that gets invoked is the one in the subclass. The version of the hidden method that gets invoked depends on whether it is invoked from the superclass or the subclass."
So if they are both static methods and you invoke the method from the super class, then the super class method is invoked, not the subclass method. So really, no overriding is taking place.
While I was working on an Android program, I had the same problem on my Java classes. It turned out that the problem was not in the classes but the way Android framework processes screen output.
for example if output was programmed in the onCreate() method in the parent class, Android failed to correctly fetch the output of overridden methods from child classes beyond first child. Honestly I don't understand whole method calling order.
To resolve the issue I simply programmed the output in the onResume() and now it seem to work fine.

Categories

Resources