Reputation: 3651
I have class Attribute
class Attribute{
private Parser parser;
private String value;
private ParserType parseType;
}
and Enum
Enum ParserType{
STRING,NUMBER,RANGE
}
and parser interface
interface Parser<S,T>{
T parse(S s){
}
}
now for based on different data type i am parsing value in different way. So for that i created classes
class StringParser implements Parser<String,String>{
@override
public String parse(String value){
return //... parse and return string
}
In similar way i have other parser
class DoubleParser implements Parser<String,Double>{
@override
public Double parse(String value){
return //... parse and return double
}
What i am doing here is having reference of Parser in Attribute and setting different type of parser based on its ParserType
for example
class Attribute{
private Parser parser;
private String value;
private ParserType parseType;
Attribute(String value,ParserType parsertype){
this.value=value;
this.parserType=parserType
}
private void setParserType()
{
switch(parserType){
case ParserType.String:
parser=new StringParser();
break;
case ParserType.Number:
parser=new NumberParser();
break;
}
}
public void parse(){
parser.parse(value); // here return type is object... and i want it to be String if it is StringParser and bouble if it is DoubleParser
}
}
if you see parse() method in Attribute class. I want it to give String data type if it is StringParser and double if it is DoubleParser
I know i am doing something wrong there using generics. So my question is What is the best practice to achieve this?
UPDATED
Thanks for Answer guys.. But Now i want to store that Attribute in a Map but when i do something like this it return me Object
// I did changes in my Attribute class
public T parse(){
return parser.parse(value); // here return type is object... and i want it to be String if it is StringParser and bouble if it is DoubleParser
}
Map<String,Attribute> map;
//assuming my map has some entries
for(Map.Entry<String,Attribute> m:map.entrySet()){
map.getValue().parse(); // this parse methods returns object to me here. I want it to be some specific type like String or Double
}
Upvotes: 0
Views: 219
Reputation: 3757
You can do something like this.
class Attribute<T, R> {
private final T value;
private final Parser<T, R> parser;
public Attribute(T value, Parser<T, R> parser) {
this.value = value;
this.parser = parser;
}
private R parse() {
return parser.parse(value);
}
private interface Parser<T, R> {
R parse(T t);
}
private static class StringParser implements Parser<String, String> {
@Override
public String parse(String s) {
return s;
}
}
private static class DoubleParser implements Parser<String, Double> {
@Override
public Double parse(String s) {
return Double.parseDouble(s);
}
}
public static void main(String[] args) {
Attribute<String, String> stringAttribute = new Attribute<>("input", new StringParser());
Attribute<String, Double> doubleAttribute = new Attribute<>("1.0", new DoubleParser());
System.out.println(stringAttribute.parse()); //should print the string
System.out.println(doubleAttribute.parse()); //prints the double value
}
}
Note - I have added all the interfaces and classes in the same class to keep the example in a single file for you to copy and run without creating multiple files.
I also changed the structure a little to make it more readable. You can provide the parsers during construction of the attribute class rather than keeping the ParserType in the class and then deciding what parser to instantiate. Attribute class should not be responsible for doing that.
Upvotes: 1
Reputation: 3916
Provide your return type while creating object of Attribute.java
Parser.java
interface Parser<S,T>{
T parse(S s);
}
StringParser.java
public class StringParser<S> implements Parser<String, S>{
@Override
public S parse(String s) {
return (S) "Hello";
}
}
DoubleParser.java
public class DoubleParser<S> implements Parser<Double, S>{
@Override
public S parse(Double s) {
return (S) new Double(1);
}
}
Attribute.java
public class Attribute<T, R> {
public T value;
private Parser<T, R> parser;
public Attribute(T value, String parserType) {
switch (parserType) {
case "ParserTypeString":
parser = (Parser<T, R>) new StringParser<R>();
break;
case "ParserTypeNumber":
parser = (Parser<T, R>) new DoubleParser<R>();
break;
}
}
public R parseReturn() {
return parser.parse(value);
}
}
Test.java
public class Test {
public static void main(String[] args) {
Attribute<String, String> str = new Attribute<String, String>("World", "ParserTypeString");
System.out.println(str.parseReturn());
Attribute<Double, Double> dbl = new Attribute<Double, Double>(5D, "ParserTypeNumber");
System.out.println(dbl.parseReturn());
}
}
Upvotes: 1