If I have an Enum as a helper in a Java class, is there any way to refer to that Enum outside of the class it's helping?
Basically, what I have is this:
class Account extends MyClass {
HashMap<Property, String> property = new HashMap<Property, String>();
public Account() {
}
public enum Property {
USERID,
PASSWORD;
}
}
I want to be able to access the Property enum outside of the Account class.
The reason I want to do this is because this is a subclass of a another, and I want to be able to access the properties of a given subclass without refering to a unique enum name (ie: without refering to each one as, say, AccountProperty or ResearchProperty or TaskProperty... etc).
Your enum is public so you just can use Account.Property to access it from outside the Account class
EDIT :
If I got what you need, you'd like to do something like
Property p = Account.Property.PASSWORD;
Property p1 = Product.Property.CODE;
where Product is
public class Product extends MyClass{
HashMap<Account.Property, String> property = new HashMap<>();
public Product() {
}
public static enum Property {
CODE,
PRICE;
}
}
and you want to do this in your MyClass.
The problem is that both the two lines require an import and you can't import two classes with the same name, so the only solution is to do something like this
Account.Property p = Account.Property.PASSWORD;
Product.Property p1 = Product.Property.CODE;
I guess that you've got to deal with the instanceof to use the right Property enum for each class, as there's no way to extend an enum!
maybe something like the following (but this has no type checking):
import java.util.*;
abstract class MyClass {
Map<Object,String> properties=new HashMap<Object,String>();
}
class Account extends MyClass {
enum Property {
userid,password
}
//static Set<Property> keys=EnumSet.allOf(Property.class);
}
class Research extends MyClass {
enum Property {
red,green;
}
static Set<Property> keys=EnumSet.allOf(Property.class);
}
public class So10666881 {
public static void main(String[] args) {
Account account=new Account();
account.properties.put(Account.Property.userid,"user");
account.properties.put(Account.Property.password,"pass");
for(Account.Property property:Account.Property.values())
System.out.println(property+"="+account.properties.get(property));
}
}
Just declare the enum as a public top level enum class (in its own file)
Related
Super.java
package x.y.z;
public abstract class Super {
public CustomClass a() {
return new CustomClass();
}
public abstract String getName();
public abstract String getDescription();
}
Sub.java
package x.y.z;
public abstract class Sub extends Super {
public String getDescription() {
return "Is a Sub";
}
}
User.java
package x.y.z;
public class User {
private class UseCase extends Sub {
public String getName() {
return "UseCase";
}
}
public UseCase use() {
return new UseCase();
}
}
In another part of my app I try to access new User().use().a(), and I think this causes the error (it's a compile-time error though).
Trying to compile the above errors:
a() in x.y.z.Super is defined in an inaccessible class or interface
What's causing this error and how do I fix it?
New question
This makes the error disappear for me:
User.java
package x.y.z;
public class User {
private class UseCase extends Sub {
public String getName() {
return "UseCase";
}
}
public Super use() {
return new UseCase();
}
}
Changing the type of User.use() to Super "fixes" the error.
Is this a problematic "fix", or will this work fine without any hiccups?
a() in x.y.z.Super is defined in an inaccessible class or interface
Because a UseCase class, that you are trying to return, is private. Consider the following example, that compiles without errors:
User user = new User();
Sub sub = user.use(); // because of implicit up-casting to Sub (and Sub is public)
sub.a();
If you want to fit these 3 lines into a single expression, you need an explicit cast:
CustomClass custom = ((Sub) new User().use()).a();
Also, as you've already pointed out, you can change the use(...) method return type to a Sub or a Super class, so the following code will work without additional casts:
CustomClass custom = new User().use().a();
The problem here is that the type that you return from User#use (i.e. UseCase) is private to the User class, prohibiting it from being accessed from anywhere outside User. Modifying UseCase to be public instead of private should fix your issue.
public class UseCase extends Sub {
#Override
public String getName() {
return "UseCase";
}
}
I have a following Java Code where enum data type is used to create instances of the base class as following:
Main Abstract Class:
public abstract class Element{
static enum elements{
quad8{Element create(){return new ElementQuad2D();}};
abstract Element create();
}
public static Element newElement (String name){
el=elements.valueOf(name);
return el.create();
}
public Element (String name, int nind, int nstress){
this.name = name;
/*Do Something Else*/
}
}
SubClass:
class ElementQuad2D extends Element{
public ElementQuad2D(){
super("quad8",8,4);
}
}
How to create enum type as above such that I can create the instance of different subclass based on element name like "quad8" in PYTHON?
This can be easily achieved with a dictionary from a string to the class. The use of subclasses doesn't play a role here:
class Element: pass
class ElementQuad2D(Element): pass
mapping = {'quad8': ElementQuad2D}
obj = mapping['quad8']()
print(obj)
# <__main__.ElementQuad2D object at 0x01D70BD0>
I am currently working on designing some system where I'm confused if it will be right to control base class attributes with derived class.
For example:
Class Building {
String name;
String[] facilities;
}
Class OfficeBuilding extends Building{
}
Class ResidentialBuilding extends Building {
}
//Type of Building control attribute like facilities here which is empty by default. Should it be part of Derived classes or it should remain part of Base class and derived classes should just override its values ?
Things to keep in mind:
1). All classes are data classes here.
2). Base class facilities attribute is always empty and controlled by child class.
Thanks.
There is more than one solution. Not knowing your use case I would say name and facilities can be fully managed by parent class, not even directly accessible from child classes (only via constructor / some methods). I would also store facilities as list:
Class Building {
private String name;
private List<String> facilities;
public Building(String name, String... facilities) { // facilities won't be null this way
this.name = name;
this.facilities = new ArrayList<String>(Arrays.asList(facilities));
}
public Building(String name) {
this(name, new String[0]);
}
// Only if this makes sense
public Building() {
this("");
}
public String[] getFacilities() {
return facilities.toArray(new String[facilities.size()]);
}
// if needed you can...
public void addFacility(String facility) { ... }
public void removeFacility(String facility) { ... }
}
Class OfficeBuilding extends Building {
public OfficeBuilding() {
super("Office", "facility1", "facility2");
//...
}
}
I would like to store the class object of several classes that extend an abstract class in an array list. Please be aware, that I have to use an abstract class and no interface, because the class Country will contain more functionality.
The idea is to later access this class objects, create an object of them and call a method.
Question: How can I achieve this, because the following code produces errors.
import java.util.ArrayList;
public class Main
{
public static void main(String args[]) {
new Main();
}
public Main() {
// The idea is to add the class of all specific countries to the countries array
ArrayList<Class<Country>> countryclasses = new ArrayList<Class<Country>>();
// Doesn't work
countryclasses.add(England.class);
// Doesn't work
Class<Country> englandclass = England.class; // Error
countryclasses.add(englandclass);
// Doesn't work
England england = new England();
Class<Country> country = england.getClass().getSuperclass().getClass();
// Class<Country> country = england.getClass().getSuperclass().getClass();
countryclasses.add(country);
for(Class<Country> countryclass : countryclasses) {
// Create an object from the class
// Call the getName() method
}
}
public abstract class Country {
abstract String getName();
}
public class England extends Country {
public String getName() {
return "England";
}
}
}
If you really want to have a List<Class> instead of using a polymorphic collection of instances, you can use an upper-bounded wildcard to define classes that will be Country or extend it:
List<Class<? extends Country>> countryclasses = new ArrayList<Class<? extends Country>>();
Class<? extends Country> englandclass = England.class;
countryclasses.add(englandclass);
I am trying to create a generic Identifier class which I would be able to use as follows:
public class TestGenericIdentifier {
public static void main(String[] args) {
Identifier<Car> carId = new Identifier<>(Car.IdentifierType.LICENSE_PLATE, "123 XYZ");
Identifier<Person> personId = new Identifier<>(Person.IdentifierType.SOCIAL_SECURITY, "123456");
System.out.println(carId);
System.out.println(personId);
}
}
To get there, I started by creating an Identifiable interface:
public interface Identifiable<T extends Enum> {}
The idea being that a class that implements Identifiable needs to provide an enum T in its declaration which is the type of the first parameter of the Identifier constructor:
public class Identifier<E extends Identifiable<T>> { //does not compile
public Identifier(T type, String value) {
//some code
}
}
Now the code above does not compile as I can only use Identifiable (no parameter T) on the first line. If it worked I would be able to write the following two classes:
public class Car implements Identifiable<Car.IdentifierType>{
public enum IdentifierType {
SERIAL_NUMBER,
LICENSE_PLATE;
}
}
public class Person implements Identifiable<Person.IdentifierType> {
public enum IdentifierType {
DATABASE_ID,
SOCIAL_SECURITY;
}
}
Is there a way to do that using generics?
EDIT
One way is to compromise conciseness and keep compile-time type checking by doing:
public class Identifier<T extends Enum> {
public Identifier(T type, String value) {
}
}
and the main function becomes:
Identifier<Car.IdentifierType> carId = new Identifier<>(Car.IdentifierType.LICENSE_PLATE, "123 XYZ");
Identifier<Person.IdentifierType> personId = new Identifier<>(Person.IdentifierType.SOCIAL_SECURITY, "123456");
public class Identifier<E extends Identifiable<? extends Enum>> {
public Identifier(Enum type, String value) {
//some code
}
}
Might be enough for what you want
You can get this to compile by tweaking your code a bit but I'm not sure it's what you want. The following seems to work for me.
Identifier<Car.IdentifierType, Car> carId =
new Identifier<Car.IdentifierType, Car>(Car.IdentifierType.LICENSE_PLATE,
"123 XYZ");
public static class Identifier<T extends Enum, E extends Identifiable<T>> {
public Identifier(T type, String value) {
// some code
}
}
The question is why do you want to do this? If you edit your question some more with the background, I can edit my answer to be more helpful.