#Return type for a generic method

76 messages · Page 1 of 1 (latest)

sleek trench
#

Hello! I was writing a class Operation which takes in 2 Operands (which have an eval method they override from an Operable interface) and a char operator and results in the corresponding output. However, there is an added demand that if the '+' operator is used, we must only ensure they are strings, or else we throw an exception -- or similarly if the * operator is used, we must ensure they are integers or throw an exception. I attempted to write my overriden eval function in Operation with the same generic return type as the one we declare at Operation. However, even upon casting, it says my wrapper Integer class cannot be converted to the return type T. How may I fix this?

Code: ```java
class Operation<T> implements Operable<T> {

private char s;
private Operand<T> o1;
private Operand<T> o2;

private Operation(char s, Operand<T> o1, Operand<T> o2) {
this.s = s;
this.o1 = o1;
this.o2 = o2;
}

public static <T> Operation<T> of(char s, Operand<T> o1, Operand<T> o2) {
return new Operation(s, o1, o2);
}

@Override
public T eval() {

if (this.s == '*') {
  if (o1.eval() instanceof Integer && o2.eval() instanceof Integer) {
    int a = (Integer) o1.eval();
    int b = (Integer)o2.eval();
    return a*b;
  }
  throw new InvalidOperandException(s);

}

else if (this.s == '+') {
  if (o1.eval() instanceof String && o2.eval() instanceof String) {
    return (String)o1.eval() + (String)o2.eval();
  }
  throw new InvalidOperandException(s);
}

else if (this.s == '^') {
  if (o1.eval() instanceof Boolean && o2.eval() instanceof Boolean) {
    return o1.eval() ^ o2.eval();
  }
  throw new InvalidOperandException(s);
}
else {
  return null;
}

}

}

next pendantBOT
#

This post has been reserved for your question.

Hey @sleek trench! Please use /close or the Close Post button above when you're finished. Please remember to follow the help guidelines. This post will be automatically closed after 300 minutes of inactivity.

TIP: Narrow down your issue to simple and precise questions to maximize the chance that others will reply in here.

sleek trench
#

Operand.java for reference

class Operand <T> implements Operable<T>{

  private T content;

  public Operand (T content) {

    this.content = content;
  }

  @Override
  public T eval() {
    return this.content;
  }
}
shy sky
#

(nitpick btw, unless Operable has a default eval, they implement the method, not override it)

sleek trench
#

operable is an interface with an abstract method eval so wouldnt it override it?

shy sky
#

abstract methods are implemented rather than overridden

#

it's not that different, it's just more specific terminology

sleek trench
#

gotcha

shy sky
#

if it has an implementation, it's overridden
if it doesn't, it's implemented

#

so the first implementation is well, the implementation, then anything on that same signature is an override

#

im a bit confused on the overall structure, why not have separate classes for each operation? then you could have class Addition extends Operation<Integer> or whatever

sleek trench
#

oh shoot yeah that makes sense

#

but if it inherits from an abstract method which has a return type T. it needs to have the same signature right?

#

so i cant do something like

#
public int eval() {
...
}

if it inherits from an interface with signature

public T eval();

```?
shy sky
#

you're providing a concrete type for the generic

#

when you specify the generic, you're creating a new class where the generic is replaced by the type provided, that includes extends and implements clauses for classes.

the most often case is doing Child<T> extends Parent<T>, which still does the above but it just results in the generics in the parent now pointing to the generics of the child

but when you provide a concrete type, like extends Operation<Integer> here, you're using a class where T in Operation<T> is all replaced by Integer, just like if you were using an Operation<Integer> for anything else

sleek trench
#

I see. does making operation an abstract method with the factory method which instantiates a subclass [addition, multiplication, etc] based on the type of operator make sense?

#

so that way my operation doesnt actually have a constructor

#

it just has a factory method that instantiates my subclasses

#

which have constructors

shy sky
#

you mean operation as an abstract class?

#

i'd say you would have Operation as an abstract class for the structure of having 2 operands and all that (if that's all you're dealing with, Negation wouldn't work with that obviously)
but not a factory method, no. let each class be handled automatically. checking to see which operation it should be requires outside knowledge of the children of itself and their specifications.
let it be explicit at the callsite. you can't just check the operand, for example. + is used for both Addition and Concatenation.

lavish star
shy sky
#

no not really how it works

#

even in the example and description, Strings and Booleans are mentioned

#

oh yeah that reminds me, instead of the generic Operation class, you could have a more specific BinaryIntegerOperator extends Operable<Integer>

sleek trench
#

if i want the operands of the operation to also potentially be an operation themselves how may i do that?

#

i was thinking of making operand inherit from operation but im not sure how this will work

shy sky
#

you just.. do that

shy sky
#

you would have an identity unary "operator" that evals to its operand

shy sky
lavish star
#

eval method is more like for numbers

shy sky
#

??? lmao no

lavish star
#

he should do T extends Number

shy sky
#

evaluation is for any expression, it isn't related to numbers specifically

sleek trench
#

nooo the specifications of the question were such that certain types of operations only demanded certain types

shy sky
#

even in math, evaluation isn't always about numbers

#

operators can operate on sets, on relations, on functions

shy sky
lavish star
shy sky
#

i honestly have no idea what you're going on about, fertiz

lavish star
#

that this code would turn into else if catastrophy

shy sky
#

or you could just use classes properly like i suggested

#

i still have no idea what you're going on about

#

a hierarchy of classes is perfect for this sort of task. i've done it before

lavish star
#

instead of else if's he might nodify the T

#

T extends Number | String | Boolean

shy sky
#

yikes, no

#

hell no

lavish star
#

and no if's needed

shy sky
#

wtf are you even talking about

#

that isn't valid java

#

and it doesn't work logically, either

#

you could just use classes

lavish star
shy sky
#

no it wouldn't lmao

#

please stop

#

you're just embarassing yourself

lavish star
#

no

#

useless if's

shy sky
#

no ifs are needed

#

and no bullshit input from you is needed either. please leave.

#

T extends Number | String | Boolean is not valid java.

#

this kind of structure works fine. i've used it before

lavish star
#

why static classes

shy sky
#

even works for entire grammars

shy sky
# lavish star why static classes

was for codingame and i just tend to put everything in the Solution class for some weird reason. you obviously don't have to make them nested classes

lavish star
shy sky
#

not really

#

i'd say it's just the right amount of engineering

#

the pattern as a whole has worked wonders with parsing