Inheritance and Generics in Java - java

so I am making a project and I have some questions about inheritance.
I have two classes, named Attribute and NumericalAttribute. The first one:
public class Attribute {
Attribute() {}
Attribute(String type) {}
}
(which should be abstract, but i need to instantiate it so it can't be)
and the other one:
public class NumericalAttribute extends Attribute {
double value;
NumericalAttribute(String value) { this.value = Double.parseDouble(value); }
public double getAtr(Attribute atr) { return this.value; }
}
I have multiple children of Attribute, and each one of them has the same structure but it represents another type (string, int, boolean). The thing is I need some kind of method to return the "value" variable (which I do have in NumericalAttribute) but for the attribute class. But I can't create a method in Attribute, since each one of the sons will have a different type of return. So is there any way so that I can obtain the "value" variable through Attribute?
Thank you very much!
public static Atributo transformAtributo(String tipo, String valor) {
Atributo atr = new Atributo();
if (tipo.equals("bool")) atr = new AtributoBoolean(valor);
else if (tipo.equals("string")) atr = new AtributoCategorico(valor);
else if (tipo.equals("num")) atr = new AtributoNumerico(valor);
else if (tipo.equals("set")) atr = new AtributoCategoricoMultiple(valor);
else if (tipo.equals("fecha")) atr = null;
return atr;
}

This is what you are looking for:
public abstract class Attribute<T> {
public abstract T getValue(Attribute attr);
}
public class NumericalAttribute extends Attribute<Double> {
double value;
#Override
public Double getValue(Attribute attr) {
return value;
}
}
public class TextAttribute extends Attribute<String> {
String value;
#Override
public String getValue(Attribute attr) {
return value;
}
}
Attribute<T> is a generic class. The return type is declared on each concrete class.

Related

Java class property with type unknown at compile time

I have a Java class with a property that can be either a String, a boolean or a List.
What would be the best approach to declare that property type? Knowing that I can only know its type at Runtime.
My first approach was to define that property with type Object, but not sure if there's a better way to achieve this.
private final String expression;
private Object expressionValue;
ParsedExpression(String expression, Person person) {
this.expression= expression;
expressionEvaluator(person);
}
private void expressionEvaluator(Person person) {
switch (this.expression) {
case "name":
expressionValue = person.getName();
break;
case "adult":
expressionValue = person.isAdult();
break;
case "addresses":
expressionValue = person.getAddresses();
break;
default:
throw new RuntimeException("Property does not exist on type Person");
}
}
If you have a very few types and not going to change them you can use a generic class with a private constructor and a few factory methods which allow creating an instance only with specified type parameters:
public final class ExpressionValue<T> {
private final T value;
private ExpressionValue(T value) {this.value = value;}
public Optional<String> getAsString() {
return (value instanceof String) ? Optional.of((String)value) : Optional.empty();
}
public Optional<Boolean> getAsBoolean() {
return (value instanceof Boolean) ? Optional.of((Boolean) value) : Optional.empty();
}
// in this context empty collection and empty optional mean different things
#SuppressWarnings("OptionalContainsCollection")
public Optional<List<?>> getAsList() {
return (value instanceof List) ? Optional.of((List<?>) value) : Optional.empty();
}
public void use(Consumer<? super String> stringUser, Consumer<? super Boolean> booleanUser, Consumer<? super List<?>> listUser) {
getAsString().ifPresent(stringUser);
getAsBoolean().ifPresent(booleanUser);
getAsList().ifPresent(listUser);
}
public static ExpressionValue<String> fromString(String string) {
return new ExpressionValue<>(string);
}
public static ExpressionValue<Boolean> fromBoolean(boolean bool) {
return new ExpressionValue<>(bool);
}
public static ExpressionValue<List<?>> fromList(List<?> list) {
return new ExpressionValue<>(list);
}
}
If you have many available types or need more flexibility of types you can use a hierarchical approach. In this case, you need to create an interface with common String, boolean and List methods, and then create implementations of this interface with all available type parameters. It may look like this:
public interface ExpressionValue<T> {
boolean check();
}
public abstract class ExpressionValueSkeleton<T> implements ExpressionValue<T> {
private T value;
public ExpressionValueSkeleton(T value) {
this.value = value;
}
protected T getValue() {
return value;
}
}
public class StringExpressionValue extends ExpressionValueSkeleton<String> {
public StringExpressionValue(String value) {
super(value);
}
#Override
public boolean check() {
return !getValue().isEmpty();
}
}
public class BooleanExpressionValue extends ExpressionValueSkeleton<Boolean> {
public BooleanExpressionValue(Boolean value) {
super(value);
}
#Override
public boolean check() {
return getValue();
}
}
public class ListExpressionValue<E> extends ExpressionValueSkeleton<List<E>> {
public ListExpressionValue(List<E> value) {
super(value);
}
#Override
public boolean check() {
return !getValue().isEmpty();
}
}
If you want perform some operations which are available only for some types you can use Acyclic Visitor pattern.

How to check class validity with generic class

I'm working on code where I have to cast base class onto derived one where I have an array of generic types that are derived by the base on.
For example, I have Base and Derived1, Derived2 and I put them into Class[]{Derived1.class, Derived2.class} and I pass this array to the constructor of the class.
In this constructor, I have to create instances of these derived classes and I don't know how to do that because I get the info that Class and Base are incompatible.
Here is my code example
public abstract class Base {
public abstract Base create(String s);
}
public class Derived extends Base {
java.lang.Integer value;
private static Derived integer = new Derived();
public static Derived getInstance(){
return integer;
}
public Base create(String s) {
value = java.lang.Integer.parseInt(s);
return this;
}
}
public class Clazz {
Class<? extends Base> type;
ArrayList<Base> arrayList;
public Class<? extends Base> getType() {
return type;
}
}
public class AnotherClazz{
ArrayList<Clazz> clazzArrayList;
Class<? extends Base>[] types;
AnotherClazz(Class<? extends Base>[] args){
clazzArrayList = new ArrayList<>();
types = args; // assuming I pass 2 elements in array
String[] strings = new String[]{"1","2"};
for (int i=0; i<args.length; ++i){
if (types[i] instanceof Base){
// here i want to check validity of class
}
}
for (int i=0; i<strings.length; ++i){
clazzArrayList.get(i).arrayList.add(((types[i]) Base).getInstance().create(strings[i]));
//here i want to create instance of object from type assigned to specific column
}
}
Thanks for the help.
To check the validity, try this
if (types[i].getClass().isAssignableFrom(Base.class))
If I read the question correctly, you want to create a few instances of derived classes that all have the same constructor arguments. If that is the case, then you need to give each derived class the same constructor (it does not need to be in the base class) and use Constructor.newInstance(parameters) to create the instances. Further, since you want to ensure that each derived class extents the base class then you will want to use Class.isAssignableFrom(class). For example,
import java.lang.reflect.Constructor;
public class SO52930530 {
public abstract static class Base {
public abstract <T> T getValue();
}
public static class Derived1 extends Base {
String value;
public Derived1(String value) {
this.value = value;
}
public <T> T getValue() {
return (T) value;
}
}
public static class Derived2 extends Base {
Integer value;
public Derived2(String value) {
this.value = new Integer(value);
}
public <T> T getValue() {
return (T) value;
}
}
public static void main(String... args) throws Exception {
Class<? extends Base>[] extensions = new Class[]{Derived1.class, Derived2.class};
String[] values = new String[]{"a", "1"};
Base[] instances = new Base[values.length];
for (int i = 0; i < instances.length; i++) {
Class extension = extensions[i];
if (Base.class.isAssignableFrom(extension)) {
Constructor constructor = extension.getConstructor(String.class);
instances[i] = (Base) constructor.newInstance(values[i]);
}
}
for (int i = 0; i < instances.length; i++) {
System.out.printf("%d %s %s\n", i, instances[i].getClass(), instances[i].getValue());
}
}
}
I hope this helps.
Thanks for helping with checking validity (it works!) but I still don't get this newInstance creation because I have to read data from .csv file and my derived classes are in fact "wrappers" for primitive types like int, float, etc. and I am supposed to create new object using methods getInstance() and create(string s), so it looks like this:
public static class Derived1 extends Base { //Integer wrapper
Integer value;
public Derived1(Integer value) {
this.value = value;
}
private static Integer integer = new Integer();
public static Integer getInstance(){
return integer;
}
private Integer(){};
public Base create(String s) {
value = java.lang.Integer.parseInt(s);
return this;
}
}
and I don't know how to use Class to cast to appriopriate type.

Returning a generic object on Java from abstract class

I have a class that should accept different datatypes as the second constructor parameter:
public abstract class QueryMatch {
String key;
Object input;
public <T> QueryMatch(String key, T o) {
this.key = key;
input = o;
}
public String getKey() {
return key;
}
public Object getValue() {
return input;
}
}
I don't want to use type parameters, like
public abstract class QueryMatch<T>{
String key;
T input;
...
As this way I'm getting raw types warnings when declaring retrieving QueryMatch as a generic (as I don't know the datatype it contains). But the problem is that I need to return the value and I'm not totally comfortable by returning an Object (is that just me, but it doesn't seem like a good practice?).
Additionally, another class inherits from it:
public class QueryMatchOr extends QueryMatch {
public QueryMatchOr() {
super("title", new ArrayList<String>());
}
public void addMatch(String match) {
((ArrayList<String>) input).add(match);
}
}
And of course I'm getting a Unchecked cast warning (which I can avoid with #SuppressWarnings(“unchecked”)).
So, my question is... is there a better way to achieve what I'm trying to do? An abstract class that contains an object (which could be bounded), and returning the datatype it contains (instead of an Object) without using a type parameter in the class declaration?
What you are doing is not a good design. You are using an Object type field from the superclass while you only can know it's actual (needed) type in the subclass. If you only know that in the subclass, declare that variable in the subclass. Not even to mention that your fields are not private.
How about:
public abstract class QueryMatch {
private String key;
public QueryMatch(String key) {
this.key = key;
}
public String getKey() {
return key;
}
public abstract void addMatch(String match);
}
public class QueryMatchOr extends QueryMatch {
private ArrayList<String> input;
public QueryMatchOr() {
super("title");
input = new ArrayList<String>();
}
public void addMatch(String match) {
input.add(match);
}
}
If you need the getValue() method in the superclass, you really should make it generic:
public abstract class QueryMatch<T> {
private String key;
public QueryMatch(String key) {
this.key = key;
}
public String getKey() {
return key;
}
public abstract void addMatch(String match);
public abstract T getValue();
}
public class QueryMatchOr extends QueryMatch<ArrayList<String>> {
private ArrayList<String> input;
public QueryMatchOr() {
super("title");
input = new ArrayList<String>();
}
public void addMatch(String match) {
input.add(match);
}
public ArrayList<String> getValue(String match) {
input;
}
}
So first, I think the best answer is to make your class generic. But if you really don't want to do this you could do something like this:
public <T> T getValue(Class<T> type) {
return (T)input;
}
In some way you need to provide the expected type for the return value to the class. This can either be done my making that class generic or the method generic.
So, my question is... is there a better way to achieve what I'm trying to do?
No, there isn't.
I think you should use generics instead of #SuppressWarnings(“unchecked”))

Type specific constructor for generic class

I have the following generic class:
public class DropdownItem<V, D> {
private V value;
private D display;
public DropdownItem(V value, D display) {
this.value = value;
this.display = display;
}
public V getValue() {
return value;
}
public void setValue(V value) {
this.value = value;
}
public D getDisplay() {
return display;
}
public void setDisplay(D display) {
this.display = display;
}
}
How do I create a constructor for specific types?
For example,
public DropdownItem(CustomClass custom) {
this(custom.getFoo(), custom.getBar());
}
or
public DropdownItem(CustomClass custom) {
this.value = custom.getFoo();
this.display = custom.getBar();
}
Neither of those solutions work. It does work to do this when implementing the generic class:
DropdownItem<Integer, String> myItem = new DropdownItem<Integer, String>(custom.getFoo(), custom.getBar());
However, I would like to include a constructor in the generic class to accomplish this. Any ideas?
It looks like a factory method, in addition to the existing constructor, can help you:
public static DropdownItem<Integer, String> getCustomClassInstance(CustomClass custom)
{
return new DropdownItem<Integer, String>(custom.getFoo(), custom.getBar());
}
It can't be another constructor. Your class is generic, so any constructor must deal with generic types V and D to assign them to value and display. it can't be specific types in the constructor(s) for this generic class.

Generics implementation using interface with generics

I have an interface Value and a class Record
public interface Value<T> {
T getRawValue();
}
public class Record<Value<T>> {
private Value<T> value;
T getRecordRawValue() {
return value.getRawValue();
}
}
Java will not compile this and complains about the Generics declaration > . Could someone enlighten me as to why this is invalid syntax?
You need bound your generic type to indicate the requirement of it being a Value<T>, and you also need to preserve the type that value Value<T> is providing, therefore your Record class requires two generic types: T: The type of the values returned and U: the type that represents a Value<T>
public class Record<T, U extends Value<T>>
Here you have a full example of this:
public interface Value<T> {
T getRawValue();
}
public class Record<T, U extends Value<T>> {
public Record(U value) {
this.value = value;
}
private U value;
T getRecordRawValue() {
return value.getRawValue();
}
}
public class StringValue implements Value<String> {
#Override
public String getRawValue() {
return "raw";
}
}
public class StrongValue implements Value<String> {
#Override
public String getRawValue() {
return "Rrrrraaawww";
}
}
public class StringRecord extends Record<String, StringValue> {
public StringRecord(StringValue valueProvider) {
super(valueProvider);
}
public String report() {
return super.getRecordRawValue();
}
}
The code public class Record<Value<T>> attempts to declare a generic type parameter for the class called Value<T>, but when declaring a generic type parameter, it should be a simple identifier such as T.
Try
public class Record<T>
Your Record class is wrongly declared. It should be
public class Record<T> {
//contents...
}

Categories