Can individual values of an enum implement an interface - java

An enum can implement an interface. Is it possible for some of the values to implement an interface? The use case that I am thinking of is a tagging interface, so something like the following:
interface Foo {}
interface Bar {}
enum Widgets {
FOO implements Foo,
BAR_1 implements Bar,
BAR_2 implements Bar
}
That does not compile under Java 1.8. I know that internally, there are separate classes created for FOO and BAR_1, so it seems this is possible, but I can easily see the standard not supporting it.
Something similar that should work is
interface Widgets;
enum Foo implements Widgets { FOO };
enum Bar implements Widgets { BAR_1, BAR_2 };
This has the drawback that I cannot just do Widgets.values() and get all of the Widgets.

The Java Language Specification states
The optional class body of an enum constant implicitly defines an
anonymous class declaration (§15.9.5) that extends the immediately
enclosing enum type. The class body is governed by the usual rules of
anonymous classes; in particular it cannot contain any constructors.
Instance methods declared in these class bodies may be invoked outside
the enclosing enum type only if they override accessible methods in
the enclosing enum type (§8.4.8).
An anonymous class can only extend (or implement) the type specified in the new instance creation expression, your enum type in this case. As such, you can't have it additionally implement an interface.
The following
enum Foo {
CONSTANT
}
gets compiled to something similar to
class Foo extends Enum<Foo> {
private Foo() {/* calling Enum superconstructor */}
public static final Foo CONSTANT = new Foo();
}
If you wanted the constant to have a body (to override or declare some methods)
enum Foo {
CONSTANT {
public String toString() {
return name().toUpperCase();
}
}
}
becomes something like
class Foo extends Enum<Foo> {
private Foo() {/* calling Enum superconstructor */}
public static final Foo CONSTANT = new Foo() { // no way to express an additional interface
public String toString() {
return name().toUpperCase();
}
};
}

The enum values are not classes but instances, so they cannot implement an interface.
However, if what you want is just a way to "tag" your values, you can use a field:
enum Widgets {
FOO(true, false),
BAR_1(false, true),
BAR_2(false, true),
BOTH(true, true);
private final boolean isFoo;
private final boolean isBar;
Widgets(boolean isFoo, boolean isBar) {
this.isFoo = isFoo;
this.isBar = isBar;
}
public boolean foo() {
return isFoo;
}
public boolean bar() {
return isBar;
}
}
In that example, you will be able to enumerate your values with Widgets.values() and to know if each value is tagged "foo", "bar" or both.
An other method to "tag" you values can be:
enum Tag {
FOO,
BAR;
}
enum Widgets {
FOO(Tag.FOO),
BAR_1(Tag.BAR),
BAR_2(Tag.BAR),
BOTH(Tag.FOO, Tag.BAR);
private Tag[] tags;
Widgets(Tag... tags) {
this.tags = tags;
}
public Tag[] getTags() {
return tags;
}
}

Related

cannot subclass the final class Subject Interface

import javax.security.auth.Subject;
abstract class Department extends Subject{
String name;
}
I have this piece of code. Sadly this throws the following error: The type Department cannot subclass the final class Subject
I was reading the documentation: https://docs.oracle.com/javase/7/docs/api/javax/security/auth/Subject.html but there is nothing much on how to use it(a specific use case).
Does anyone know how you can use Subject on an abstract Class (it has to be extended by an abstract class) ?
Edit:
Edit 2: Error Using Implements:
The type Subject cannot be a superinterface of Department; a superinterface must be an interface
Since Subject class is a final class you won't be able to extend it. That's the purpose of the final keyword. The only way I see is wrapping the class and its methods. You won't be able to use the wrapper where the final class is required, but you can implement any interfaces which are on the final class.
ex:
final class Foo {
public String getSomething() {
//
}
}
class Bar {
Foo foo;
public Bar() {
foo = new Foo();
}
public String getSomething() {
foo.getSomething();
}
public String doSomethingElse() {
//
}
}
Not sure it would be helpful in your scenario tho.

How to allow a user to choose what class to initialise

I have an abstract class Foo, which contains a function a(Object o).
Depending on what implementation of Foo you use, a(Object o) is implemented slightly differently.
I want the user of the program to be able to determine what implementation of Foo is used (eg., aFoo,bFoo, cFoo, etc), but I want to cut down on my use of conditional logic so that I can add to my program more safely in the future.
I currently have an Enum eBar that holds the names of all the implementations of Foo, which the user can choose from, but I am unable to determine how to use that to initialise the class.
Store the instance of Foo to use, or add a method creating the Foo to use, in each enum instance:
public enum FooType {
A {
#Override
public Foo createFoo() {
return new AFoo();
}
},
B {
#Override
public Foo createFoo() {
return new BFoo();
}
}
public abstract Foo createFoo();
}
Then, once the user has chosen the type, all you need to do is
selectedFooType.createFoo().a(object);
[EDIT] You can do that using an Enum like below
public enum FooType {
FOO_A(aFoo::new),
FOO_B(bFoo::new),
FOO_C(cFoo::new);
//add as much as you want here
private final Supplier<Foo> fooSupp; //the aim of using a supplier is to create a new instance each time you call the create method as mentioned in the comment.
FooType(final Supplier<Foo> fooSupp) {
this.fooSupp = fooSupp;
}
public final Foo create(){
return this.fooSupp.get();
}
}
Then you can use it like this
final Foo myFoo = FooType.FOO_A.create();
myFoo.o(Object);

Equivalent to extend final class to add extra functionality in java

I want to extend final class in java to add a new method in inherited class. Which pattern should I use?
for example:
final class foo {
}
foo is a final class in java.
I want to extend this in built class to add extra functionality.
class bar extends foo {
dosomething(){
}
}
I can't extend final class. what should I do so that bar acts like foo with added functionality?
Is there a pattern to implement this functionality? So that it will execute all the functions of final class with added functionality
As you can't extend what you can do is to wrap the class and its methods. You won't be able to use the wrapper where the final class is required, but you can implement any interfaces which are on the final class
edit: Also see this discussion Equivalent to extending a final class in Java
final class Foo {
public String getSomething() {
//
}
}
class Bar {
Foo foo;
public Bar() {
foo = new Foo();
}
public String getSomething() {
foo.getSomething();
}
public String doSomethingElse() {
//
}
}

It seems that I can *reference a field before it is defined*

public enum MyEnum1 {
FOO(BAR), BAR(FOO);
private MyEnum1 other;
private MyEnum1(MyEnum1 other) {
this.other = other;
}
public MyEnum1 getOther() {
return other;
}
}
MyEnum1 generates the error Cannot reference a field before it is defined, which is quite understandable, since declaration order matters here. But why does the following compile?
public enum MyEnum2 {
FOO { public MyEnum2 getOther() { return BAR; } },
BAR { public MyEnum2 getOther() { return FOO; } };
public abstract MyEnum2 getOther();
}
FOO refers to BAR before BAR is defined, am I wrong?
The important JLS parts are this and this
A class or interface type T will be initialized immediately before the
first occurrence of any one of the following:
T is a class and an instance of T is created.
T is a class and a static method declared by T is invoked.
A static field declared by T is assigned.
A static field declared by T is used and the field is not a constant
variable (§4.12.4).
T is a top level class (§7.6), and an assert statement (§14.10)
lexically nested within T (§8.1.3) is executed.
And
The optional class body of an enum constant implicitly defines an
anonymous class declaration (§15.9.5) that extends the immediately
enclosing enum type.
So with
FOO { public MyEnum2 getOther() { return BAR; } },
BAR { public MyEnum2 getOther() { return FOO; } };
you are creating two anonymous classes extending MyEnum2.
When BAR is eventually reference either when you call Foo.getOther() or some other piece of code does MyEnum2.Bar, the type will be initialized.
you are creating enum constant with reference to yet undeclared constant in first case. In second case it does not matter because of compilation order, enumeration constants are compiled before enumeration body. I would say this is the reason. If it was not true, compilation would fail earlier because abstract method declaration is defined after the non-abstract method declaration in body of each enum constant.
Good reference - http://docs.oracle.com/javase/specs/jls/se7/html/jls-8.html#jls-8.9
When writing FOO(BAR), you are actually invoking the constructor of MyEnum1 and therefore BAR has to be evaluated, which is impossible at that moment since BAR hasn't yet been defined.
When writing FOO {...}, you are creating a new enum constant called FOO, but defining a new anonymous class. Since the class definition is only loaded ('loaded' as in 'ClassLoader') at this point and nothing is yet being evaluated, no error occurs. Then, BAR {...} is being created, the rest of your program continues, etc., and return BAR; (or return FOO;) is only evaluated when you make a method call to getOther(), which is perfectly possible at that point since both enum constants are happily alive at that point.

How do I convert an abstract class into an interface?

I have a java program which uses arraylists - these arraylists store 'variables' where 'variables' is an abstract class.
Now, to save memory, I want to use a java library called HugeCollections-VanillaJava- however this library requires an interface to be defined.
How do I convert the abstract class into an interface? What rules/restrictions do I have to follow, to correctly perform the conversion?
Finally, is it possible for me to use my abstract class with minimal code changes, so that the library that requires an interface, also works correctly? Ideally I would like not to change the abstract class at all...Is this possible?
how do I convert an abstract class into an interface?
Make a copy of the abstract class source file.
Change "class" to "interface" in the initial declaration.
Change the name (optionally, depends on what you're doing).
Remove the bodies of any methods that are implemented by the class.
Remove the word "abstract" from the other ones.
Remove all private and protected members.
Remove all constructors.
Remove the keyword "public" from the public members.
If you had any code you removed (implemented methods, private or protected stuff), have your original abstract class implement your interface and leave that stuff there.
(Incomplete) Example:
Foo as an abstract class:
public abstact class Foo
{
private int bar;
public static final int SOME_CONSTANT = 42;
public Foo(b) {
this.bar = b;
}
public abstract void doSomething(String s);
protected int doSomethingElse() {
return this.bar * 2;
}
}
Foo as an interface:
public interface Foo
{
int SOME_CONSTANT = 42;
void doSomething(String s);
}
In my case, as I did have some stuff the old Foo did, I'd probably have AbstractFoo or something:
public abstact class AbstractFoo implements Foo
{
private int bar;
public Foo(b) {
this.bar = b;
}
public abstract void doSomething(String s);
protected int doSomethingElse() {
return this.bar * 2;
}
}
...so that an implementation could use it as a starting point if desired (although with that private bar in there, it doesn't make a lot of sense).
Pattern Adapter might help you.
Imagine, you're have to use SomeClass as TargetInterface
public abstract class SomeClass {
// some code here
public abstract void someMethod();
}
public interface TargetInterface {
public void someMethodBlaBla();
}
And they have different signatures of methods - someMethod() and someMethodBlaBla().
So you're might create such adapter class:
public class Adapter implements TargetInterface {
private SomeClass adaptee;
public Adapter( SomeClass adaptee ) {
this.adaptee = adaptee;
}
public void someMethodBlaBla() {
this.adaptee.someMethod();
}
//delegate all calls to adaptee
}
and somewhere in code you might use both - adapter and instance of abstract class, without interference on current code:
SomeClass abstractClassInstance = ... //get instance of your abstract class
TargetInterface targetInterfaceInstance = new Adapter( abstractClassInstance );
If abstract class does not define any concrete methods, you can even use regular expression for that. From:
public abstract class Abstract {
public abstract void method();
//...
}
to:
public interface Interface {
void method();
//...
}
public abstract modifiers are implicit for interfaces. If the abstract class does define some methods (not all methods are abstract) or have some fields this can't be done (at least easily).

Categories

Resources