Is there any way to set a variable held in an enums parent/superclass from within an enum itself? (The following doesn't compile, but illustrates what I'm attempting to achieve)....
class MyClass{
ObjectType type;
String someValue;
public void setType(ObjectType thisType){
type = thisType;
}
enum ObjectType {
ball{
#Override
public void setValue(){
someValue = "This is a ball"; //Some value isn't accessible from here
}
},
bat{
#Override
public void setValue(){
someValue = "This is a bat"; //Some value isn't accessible from here
}
},
net{
#Override
public void setValue(){
someValue = "This is a net"; //Some value isn't accessible from here
}
};
public abstract void setValue();
}
}
Then, something like so:
MyClass myObject = new MyClass();
myObject.setType(ObjectType.ball);
After doing the above, the 'someValue' string of the myObject should now be set to 'This is a ball'.
Is there any way to do this?
A nested enum type is implicitly static (see Are java enum variables static?). That includes enum types declared as inner classes, so they can't access instance fields of the outer class.
You can't do what you're trying to do with an enum, you'll have to model that as a normal class.
You could do the following, if you want MyClass.someValue to equal the someValue of the enum, but as someValue can be retrieved from the enum I'd not bother having someValue on MyClass at all, and just retrieve it from the enum when required
public class MyClass {
ObjectType type;
String someValue;
public void setType(ObjectType thisType) {
this.type = thisType;
this.someValue = thisType.getSomeValue();
}
enum ObjectType {
ball ("This is a ball"),
bat ("This is a bat"),
net ("This is a net");
private final String someValue;
ObjectType(String someValue) {
this.someValue = someValue;
}
public String getSomeValue() {
return someValue;
}
}
}
Related
i have some redundant code that i would like to remove, my goal would be to create a method of this kind:
private GenericClass myMethod(GenericClass genericClass){
genericClass.getTipe(); //tipe1 or tipe2
genericClass.setValue("foo");
genericClass.setValue2("foo");
//some logic
return genericClass;
}
Where this method can pass two similar classes but which differ in the type of an attribute
public class Class1{
private Tipe1 tipe1;
private String value;
private String value2;
//Constructor,Getter and Setter
}
public class Class2{
private Tipe2 tipe2;
private String value;
private String value2;
//Constructor,Getter and Setter
}
What I would like to do is call the method
someServiceIml.myMethod ("Foo")
passing either an object of type Class1 or Class2 according to my needs, the business logic behind myMethod is practically the same.
This method i wish it was in the same implementation of a certain service, could you give me some solution?
Create a generic abstract type; either a super class or an interface:
public interface GenericClass<T> {
public T getTipe();
public void setValue(String s);
public void setValue2(String s);
}
Have your implementation classes implement it:
public class Class1 implements GenericClass<Tipe1> {
// leave implementation as is
}
public class Class2 implements GenericClass<Tipe2> {
// leave implementation as is
}
And type your method:
private <T> GenericClass<T> myMethod(GenericClass<T> genericClass){
T tipe = genericClass.getTipe();
genericClass.setValue("foo");
genericClass.setValue2("foo");
// some logic
return genericClass;
}
If Tipe1 and Tipe2 share a common type, you can type them too:
public interface GenericClass<T extends SomeTipe> {
public class MyClass {
public static void main(String args[]) {
Class1 c1 = new Class1();
Class2 c2 = new Class2();
GenericClass gc = myMethod(c1);
System.out.println(gc);
}
private static GenericClass myMethod(GenericClass genericClass){
genericClass.getTipe(); //tipe1 or tipe2
genericClass.setValue("foo");
genericClass.setValue2("foo");
//some logic
return genericClass;
}
}
class Class1 extends GenericClass<Tipe1>{
}
class Class2 extends GenericClass<Tipe2>{
}
class Tipe1 {
}
class Tipe2 {
}
class GenericClass<T> implements Tipe<T> {
private String value;
private String value2;
private T t;
public T getTipe() {
return t;
}
void setValue(String s) {
value = s;
}
void setValue2(String s) {
value2 = s;
}
}
interface Tipe<T> {
public T getTipe();
}
or you can cast to parent class like:
GenericClass gc = new Class2();
I need help fixing my code with the basic concepts listed above. To save from clutter, I took a screen shot of the directions here: https://imgur.com/SdiotUi
However, when I run my code it isn't working. I know there are a lot of errors but I'm having trouble fixing them even though I've spent the past few hours googling the correct way to do this.
When I create the first constructors I am not sure if I am assigning the name and legs correctly, I am having trouble returning "true", I get an error calling the parent class taking one argument, and I don't think I am overriding the abstract class correctly.
My code:
public class Animal1 {
private String animalName;
public int numberOfLegs;
public Animal1(String name){
name = animalName;
name = "John";
}
public Animal1(String name, int legs){
name = animalName;
legs = numberOfLegs;
name = "Jack";
legs = 4;
}
public String getName(){
return animalName;
}
public int getLegs(){
return numberOfLegs;
}
public void isAMammal(){
return true;
}
public void isCarnivorous(){
return true;
}
public abstract class getHello{
}
}
public class Cat1 extends Animal1{
public Cat1(String name){
Animal1.name;
}
public abstract class getHello{
return "Meow";
}
}
public class Dog1 extends Animal1{
public Dog1(String name){
Animal1.name;
}
public abstract class getHello{
return "Woof";
}
}
public abstract class Animal1 { // If you want to have an abstract method, declare the class as abstract
private final String animalName;
private final int numberOfLegs; // better of using private and make it final since it's not going to change.
public Animal1(final String name, final int legs){ //better making the input parameters final since they are not supposed to be changed
//name = animalName;
//legs = numberOfLegs;//it assigned the field to an input parameter. that will take no effect on the object created.
animalName = name;
numberOfLegs = legs;
}
public String getName(){
return animalName;
}
public int getLegs(){
return numberOfLegs;
}
public boolean isAnimal(){ //boolean function needs a return type too!!
return true;
}
public boolean isCarnivorous(){
return true;
}
public abstract String getHello(); // an abstract method has same requirement as a normal method besides the abstract modifier. it will need a return type. And it ends with a semicolon
}
public class Cat1 extends Animal1{
public Cat1(final String name){
super(name, 4); //use super to call parent constructor
}
#Override
public String getHello(){
return "Meow";
}
}
public class Dog1 extends Animal1{
public Dog1(final String name){
super(name, 4);
}
#Override
public String getHello(){
return "Woof";
}
}
First, it looks like a few of your methods are declared as classes. I assume you wanted to make them abstract methods. They need to be changed to:
public abstract String getHello();
Note that abstract methods can only be declared in an abstract class. So, you need to redefine Animal1 as abstract.
public abstract class Animal1
Next, when you implement the abstract method, you define it as
public String getHello()
If you are using an IDE like Eclipse it will automatically offer to generate this method.
Finally, when using your constructor in your child classes like Cat1, you are trying to set "name" as if it was a static variable and bypassing the constructor you already had set for Animal1. The best way to correct this is to change the constructor in Cat1 and Dog1 to call the super constructor.
public Cat1(String name){
super(name);
}
I have a few classes like this:
public class A {
private String foo;
public A(String f) {
foo = f; // I want foo to be final based on the subclass instance
}
}
public class B extends A {
private static final String FOO = "foo1";
public B() {
super(FOO);
}
}
public class C extends A {
private static final String = "foo2";
public C() {
super(FOO);
}
}
What I want is when I create an object on type B, I don't want the String in A to be changeable. foo = f just assigns a reference but I want foo to be the same final object FOO. How can I do this?
It appears you don't want a field at all, instead you can have a method.
interface A {
String foo(); // the implementation depends on the sub-class.
}
class B implements A {
public String foo() { return "foo1"; }
}
class C implements A {
public String foo() { return "foo2"; }
}
This is maybe not the best in design but what you want to do is to initialize a final String.
public class A {
private final String foo;
public A(String f) {
foo = f;
}
}
Final variables can be initialized only once, so you can initialize it in the constructor. But in your case that doesn't make sense because your subclasses are not able to access foo because it is private. See here for all available Java visibility modifiers.
I have an abstract class which has a method used by all classes that extend the class. That method is identical for each class so I don't want to have to write it over and over in those classes. The problem is that the method uses 2 variables that are declared in each class. I can't have the method in the abstract class without having those variables int eh abstract class. But if I do that, they take on the value specified in the abstract class, not the classes that extend it. How can I fix this?
Example code:
public abstract class Example {
public String property1 = ""
public String property2 = ""
public ArrayList<String> getPropertyies() {
ArrayList<String> propertyList = new ArrayList<>();
propertyList.add(property1);
propertyList.add(property2);
return property1;
}
}
public class ExampleExtension extends Example {
public String property1 = "this is the property";
public String property2 = "this is the second property";
}
You should limit the scope of the fields to private in the abstract class and declare a constructor for populating the values:
public abstract class Example {
private final String property1;
private final String property2;
protected Example(String property1, String property2) {
this.property1 = property1;
this.property2 = property2;
}
//...
}
Subclasses would then initialize the field values in their constructors by calling the super constructor:
public class ExampleExtension extends Example {
public ExampleExtension() {
super("value1", "value2");
// initialize private fields of ExampleExtension, if any
}
// ...
}
You don't have to override the variables. You can set the initial values of your properties in the constructor:
public class ExampleExtension extends Example {
public ExampleExtension() {
property1 = "this is the property";
property2 = "this is the second property";
}
}
A better way is to use a constructor with parameters though, as Mick Mnemonic suggest in the other answer.
IMO Mick's solution is the most pragmatic, although note that you also have the option to make the properties abstract, and then use subclass polymorphicism to require that subclasses override the property implementation:
public abstract class Example {
public abstract String getProperty1();
public abstract String getProperty2();
public ArrayList<String> getPropertyies() {
ArrayList<String> propertyList = new ArrayList<>();
propertyList.add(getProperty1());
propertyList.add(getProperty2());
return propertyList;
}
}
public class ExampleExtension extends Example {
public String getProperty1() { return "this is the property"};
public String getProperty2() { return "this is the second property"};
}
Make what differs(e.g. property1,property2) abstract method in this case . Search for related reading on template pattern
public abstract class Example {
public ArrayList<String> getPropertyies() {
ArrayList<String> propertyList = new ArrayList<>();
propertyList.add(getProperty1());
propertyList.add(getProperty2());
return property1;
}
public abstract getProperty1();//overriden by other class that has diff value for property1
public abstract getProperty2();//overriden by other class that has diff value for property2
}
I'm trying to prepare an interface i want to implement for Datamodel-Classes.Therefor i want to use an enum inside the interface so i know i need to implement it later.
Example:
public interface MyModelInterface {
public enum Field;
public Object get(Field field);
public void set(Field field, Object value);
}
The expected implementation:
public class MyModel implements MyModelInterface {
public enum Field {
ID("id"),
Name1("Name1"),
Name2("Name2");
private String field;
private Field(String field) {
this.field = field;
}
}
public Object get(Field field) {
//...
}
public void set(Field field, Object value){
//...
}
public static void main(String[] args) {
MyModel myModel = new MyModel();
System.out.println(myModel.get(MyModel.Field.ID));
System.out.println(myModel.get(MyModel.Field.Name1));
}
}
Since I don't know which fields the model will contain until I implement it.
I did some research and figured that enum can't be extended, so i am aware of that.
is there any way to archive this or any kind of workaround?
i don't want to use String Parameters on the getter/setter Methods to avoid using wrong values.
Thanks in advance for any suggestion.
Update:
So this is what worked for me: Splitting the interface/class in three parts, including an abstract class:
Interface:
public interface MyModelInterface<E extends Enum<E>> {
public Object get(E field);
public void set(E field, Object value);
}
Abstract Class:
public abstract class MyAbstractModel<E extends Enum<E>> implements MyModelInterface<E>{
protected final EnumMap<E, Object> fields;
public MyAbstractModel(Class<E> enumKlazz) {
fields = new EnumMap<>(enumKlazz);
}
#Override
public Object get(E field) {
return fields.get(field);
}
#Override
public void set(E field, Object value) {
this.fields.put(field, value);
}
}
Class(where i actually archive my goal):
public class MyModel extends MyAbstractModel<MyModel.Field> {
public MyModel() {
super(MyModel.Field.class);
}
public enum Field {
ID("ID"),
Name1("NAME1"),
Name2("NAME2"),
Age("AGE"),
;
private final String field;
private Field(String field) {
this.field = field;
}
public String getName() {
return field;
}
}
public static void main(String[] args) {
MyModel myModel = new MyModel();
System.out.println(myModel.get(Field.Name1));
}
}
Interface fields are static and final implicitly.
What you could do is to have an interface method returning Enum<?>, and your classes implementing it.
For instance:
interface Foo {
public Enum<?> getEnum();
}
class Bar implements Foo {
enum Blah {
INSTANCE;
}
public Enum<?> getEnum() {
return Blah.INSTANCE;
}
}
Edit
Not completely sure I understand your question update, but here's a solution that will de-couple returning a specific enum instance from an enum, by means of two interfaces.
The example is self-contained in a Main class.
public class Main {
public static void main(String[] args) {
System.out.println(new Bar().getEnumField().name());
}
static interface IHasEnum {
public Enum<? extends IMyEnum> getEnumField();
}
static interface IMyEnum {
public Enum<? extends IMyEnum> getField();
}
static class Bar implements IHasEnum {
enum Blah implements IMyEnum {
DEFAULT_INSTANCE,
THE_FIELD;
public Enum<? extends IMyEnum> getField() {
return THE_FIELD;
}
}
public Enum<? extends IMyEnum> getEnumField() {
return Blah.DEFAULT_INSTANCE.getField();
}
}
}
Output
THE_FIELD
Note
The trick here is to add a "default" instance to the enum (DEFAULT_INSTANCE), so the getField method is an instance method, hence overriding the one declared in the IMyEnum interface.
Again, not entirely sure this addresses your issue.
What you are describing is an EnumMap<E, T> - which functions like an array, with that same get-
public class MyModelBase<E extends Enum<E>> {
private final Class<E> enumKlazz;
private final EnumMap<E, Object> fields;
public MyModelBase(Class<E> enumKlazz) {
this.enumKlazz = enumKlazz;
fields = new EnumMpa<>(enumKlazz);
}
public Object get(E field) {
return fields.get(field);
}
public void set(E field, Object value) {
fields.put(field, value);
}
}
enum UserField { id, surname, name, age };
MyModelBase<UserField> userModel = new MyModelBase<>(UserField.class);
userModel.set(UserField.surname, "X");
Because of type erasure the enum map needs the class. Above the enum class is also stored as field, as some static Enum methods need the enum class. For iterating, and so on.
Java generics will be the best solution.
Lets assume, you don't know the contents of the Field as mentioned.
Create a generic interface like this:
public interface MyModelInterface<T> {
public T get();
}
Then create a class Field like this:
public class Field {
private String id;
private String name1;
private String name2;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getName1() {
return name1;
}
public void setName1(String name1) {
this.name1 = name1;
}
public String getName2() {
return name2;
}
public void setName2(String name2) {
this.name2 = name2;
}
}
and then your model class will look like
public class MyModel implements MyModelInterface<Field> {
#Override
public Field get() {
Field field = new Field();
field.setId("ID");
field.setName1("Name1");
field.setName2("Name2");
return field;
}
public static void main(String[] args) {
MyModel myModel = new MyModel();
System.out.println(myModel.get().getId());
System.out.println(myModel.get().getName1());
System.out.println(myModel.get().getName2());
}
}