Abstract Generic class - java

I have the following class :
public abstract class Step {
public abstract <S,T> S makeAStep(S currentResult, T element);
}
and I'm trying to Implement it so it will take two int's and return the sum of them , something like this :
public class sumOfInts extends Step {
public <Integer,Integer> Integer makeAStep(Integer currentResult, Integer element){
return currentResult + element;
}
}
but I get the following error :
The type sumOfInts must implement the inherited abstract method Step.makeAStep(S, T)
please help me (I need it for my programming languages course homework)
I asking very kindly to write me a code that does what I want to accomplish which wont
have any errors or warnings
thanks in front

public abstract class Step<S,T> {
public abstract S makeAStep(S currentResult, T element);
}
public class SumOfInts extends Step<Integer,Integer> {
// etc.

I agree with Jonathan's answer.
There is also another possibility, given below, that keeps the type parameters on the method itself.
It's only theory in this case, because the class and method names suggest that this has no meaning for this example.
So I change the names for my example:
public abstract class Step {
public abstract <S,T> String makeAStep(S first, T second);
}
public class ConcatTwo extends Step {
public <S, T> String makeAStep(S first, T second){
return String.valueOf(first) + String.valueOf(second);
}
}
Note : This works because the operation uses String.valueOf(Object), that works for any type (all subclass Object). For another operation, we would have to restrict S and T, using something like
S extend Integer for example.

Related

Dynamically changing #MethodSource in abstract class from a #ParameterizedTest (Jupiter-Junit 5)

I am currently writing unit tests related to GET requests, here below is a parameterized test that take a generic type E.
abstract class AbstractEntityTest< E extends Entity > {
#ParameterizedTest( name = "[{index}]: {2}" )
#MethodSource( "RoleDataProvider#provideIntArgsToTest" )
void testIntRequestsThatReturnSingle( String fileName, Integer requestParam, String testName, int index )
// do something
}
}
What I want to do is to dynamically change the method source in function of the actual type of E at runtime.
Example:
public class AnimalTest extends AbstractEntityTest< Animal > {
... }
Here E is type Animal so I would like to change the #MethodSource to
#MethodSource( "AnimalDataProvider#provideIntArgsToTest" )
Is there any way to do it ? I've been searching for hours to no avail...
That isn't going to be possible in Java I'm afraid. Java is a strongly, statically typed language, which means that objects can't change their type and type checking occurs during compilation.
Java implements generics with erasure, which means that the compiler will replace your bound type parameter E with bounding class Entity, (described here).
What are you trying to achieve? If you want to avoid duplication, you could group shared logic into a single method and call it #BeforeEach for example.
EDIT: Gotcha, I think I know what you mean, cheers for the response. Have you tried specifying that in the children test classes?
I tried messing around with the same concept but with Number, Integer, and Double. Here's what I got:
AbstractTest.java
public abstract class AbstractTest<E extends Number> {
void testIntRequestsThatReturnSingle(Number i){
System.out.println(i);
//doing the same stuff here but with the different data sources
}
public static IntStream intProvider() {
return IntStream.range(0, 10);
}
public static DoubleStream doubleProvider() {
return DoubleStream.of(0.0,1.1,2.2);
}
}
One child IntTest.java class:
public class IntTest extends AbstractTest<Integer>{
#ParameterizedTest
#MethodSource( "intProvider" )
public void intTest(Number i){
this.testIntRequestsThatReturnSingle(i);
}
}
Another child DoubleTest.java class:
public class DoubleTest extends AbstractTest<Integer>{
#ParameterizedTest
#MethodSource( "doubleProvider" )
public void doubleTest(Number i){
this.testIntRequestsThatReturnSingle(i);
}
}
This way you can minimise duplication and ensure that the right methods are called for the right classes (without any scary casting). Is this something along the lines of what you were looking for?

Java Generic: How to extend a generic class of another generic class

First, I have a simple template, nothing fancy:
public abstract class ListOfK<K> {
private List<K> insides = new ArrayList<>();
}
Next, I'm creating a service interface using the template
public abstract interface SomeService<K extends ListOfK<K>> {
int calculateSomething (K input);
int calculateAnother (ListOfK<K> list);
}
So far so good with the abstraction.
Now, let's get to the implementation
public class ListOfString extends ListOfK<String> {
}
and implementation of SomeService:
public class SomeServiceImpl extends SomeService<String> {
#Override
public int calculateSomething(String input) {
return 0; // TODO impl
}
#Override
public int calculateAnother(ListOfK listOfK) {
return 0; // TODO impl
}
}
Somehow, when SomeServiceImpl extends SomeService<String>, it marks Type parameter java.lang.String is not within its bound; should extend ListOfK<String>
What should I input as implementation of SomeService so it doesn't give error? Or do I make mistake with SomeService? I just want a class whom input is a another class using Generic.
Thanks in advance.
The key insight here is that K in the context of the ListOfK class is not the same type as K in the context of the SomeService class. In fact, in your definition of SomeService, you're saying that K needs to itself be a ListOfK, which I suspect is your problem.
Does calculateSomething need to take (1) a single value, or (2) a ListOfK of values?
Does calculateAnother need to take (1) a ListOfK of values, or (2) a ListOfK of ListOfK values?
I think you want option 1, but you've actually chosen option 2.
To fix this, don't constrain K in SomeService:
public interface SomeService<K> {
int calculateSomething(K input);
int calculateAnother(ListOfK<K> list);
}
The issue lies in the way you are defining the SomeService interface. Your code of <K extends ListOfK<K>> says that "we need a class K which extends ListOfK, which uses K as its type parameter." So that class would have to look something like:
public class Test extends ListOfK<Test> {
Which doesn't make any sense. It shouldn't only use itself inside of the list. If you change the interface to something like:
public abstract interface SomeService<K extends ListOfK<?>> {
It should fix your issue.

Unchecked overriding (well, I seem to need my generics method)

I've got generic interface Operand:
public interface Operand<T extends Operand<T>> {
T add(Operand<T> op);
T sub(Operand<T> op);
T mul(Operand<T> op);
T div(Operand<T> op);
}
which is implemented by 2 classes:
public class DoubleOperand implements Operand<DoubleOperand> {
...
}
public class RationalOperand implements Operand<RationalOperand> {
...
}
I've written "factory" interface implemented by DoubleOperandFactory and RationalOperandFactory classes:
public interface OperandFactory {
<T extends Operand<T>> Operand<T> valueOf(String s);
}
public class DoubleOperandFactory implements OperandFactory{
#Override
public Operand<DoubleOperand> valueOf(String s) { ... }
}
public class RationalOperandFactory implements OperandFactory {
#Override
public Operand<RationalOperand> valueOf(String s) { ... }
}
In my program I use an enum which objects store instance of the particular Factory:
public enum OperandType {
DOUBLE(new DoubleOperandFactory()), RATIONAL(new RationalOperandFactory());
private OperandFactory fact;
OperandType(OperandFactory fact){ this.fact = fact; }
public OperandFactory getFact() { return fact; }
}
Now I'm getting message warning "Unchecked overriding" on both factory classes, due to unchecked conversion and I'm pretty confused about this. First thing which I tried is (as it was most commonly answered here in similar topics) to replace generic method with generic factory interface, but finally it turns into impossibility to use them with the enum which should return particular factory, without <?>, as I have to create a List of operands (of generic type T extends Operand<T> for now) and fill it with the objects produced by selected factory. What would be the best way to reorganize this code?
public interface OperandFactory {
<T extends Operand<T>> Operand<T> valueOf(String s);
}
This interface does not do what you think it does.
This interface advertises that an instance of it can generate any type of operand you want. It doesn't just generate one particular kind of operand. It generates all of them.
This is not what you actually have.
What you need instead is
public interface OperandFactory<T extends Operand<T>> {
T valueOf(String s);
}
...and then to give up on the enum, because you can't have enums that have different types in them like that. That's just not a thing you're allowed to do in Java.

What does "T extends Junk" mean in a generic class in Java?

I'm trying to understand this notation of whats going on here Example also below. I'm looking to see if anyone can supply additional code to help me make sense of this. How do I extend junk with T? what does that imply?
public class Junk<T extends Junk>
{
public Junk()
{
}
public T returnType()
{
return null; //? what would I even return
}
//what would I do to make sense of this class
}
T is a generic type parameter. You know it is a Junk, or a subclass of it. To return anything useful from your method, you'd need some other methods using the same type. For example:
public class Junk<T extends Junk> {
T var;
public void setT(T var) {
this.var = var;
}
public T returnType(){
return var;
}
}
It can be used by creating instances where the type parameter is specified:
Junk junk = new Junk<Junk>();
junk.setT(new Junk<Junk>());
junk.returnType();
This is more useful than simply using "Junk" instead of "T", because subtypes can be used without losing type-safety. If you have a subclass SubclassJunk, then you can do:
Junk junk = new Junk<SubclassJunk>();
junk.setT(new SubclassJunk<Junk>());
SubclassJunk subclass = junk.returnType();
pardon me for making an educated guess, but,
It looks like T is an undefined type,
the statement <T extends junk> looks like a constraint to ensure that T derives from Junk
so if you have a class like
public class SmallJunk extends Junk
{
}
then T can be aSmallJunk, but not other types.
class Junk<T extends Junk> is the syntax for generic programming in Java. It means that wherever the type T is used in the class, it must stand for some (as yet unknown) subclass of Junk.
Given
public class junk<T extends junk<T>>
{
public T returnType()
{
return (T)this;
}
}
you would extend it as
public class Subclass extends junk<Subclass> {
}
and the inherited returnType method would then return Subclass. The most prominent example of this pattern in the standard Java libraries is enum types, where an enum Foo becomes a class that extends Enum<Foo>

Using 2 levels of generics in an Abstract Class definition

I have this generic interface:
public interface TjbListener<T> {
public void hearChange(T t);
}
Which I use like this:
public interface ObjectOneListener extends TjbListener<ClassOne> {
}
I would like to write an abstract generic class A which takes a generic type U as a parameter and has a method (1) which itself calls a method (2) on U. Below is my attempt U should extend (or implement maybe?) the generic TjbListener interface.
public abstract class ListenerInformer<U extends TjbListener<"what should I write here">> {
List<U> mListeners = new ArrayList<U>();
public void addListener(U u){
mListeners.add(u);
}
public void informAll("what should I write here"){
for(U u:mListeners){
u.hearChange("what should I write here");
}
}
}
One solution I thought of as I was writing this question is below, but I don't know if it's really a solution, or if it has subtle problems I don't understand:
public abstract class ListenerInformer<U extends TjbListener<T>,T> {
List<U> mListeners = new ArrayList<U>();
public void addListener(U u){
mListeners.add(u);
}
public void informAll(T t){
for(U u:mListeners){
u.hearChange(t);
}
}
}
UPDATE: BEWARE
I have just discovered that this approach is almost useless for my particular case because the same class cannot implement the same interface with different parameters. See the question linked below. This means that I cannot have one class be a listener of two different types with my (or Johanna's) solution, without using a different strategy like composition.
How to make a Java class that implements one interface with two generic types?
Your second example should work. But if it is as simple as that, then there is no need for the Generic U, because every instance of a subclass of TjbListener also is an instance of TjbListener.
You can do more simple:
public abstract class ListenerInformer<T> {
List<TjbListener<T>> mListeners = new ArrayList<TjbListener<T>>();
public void addListener(TjbListener<T> u){
mListeners.add(u);
}
public void informAll(T t){
for(TjbListener<T> u:mListeners){
u.hearChange(t);
}
}
}
That works as your code does and is easier to handle.
Two generic types is necessary if you need the final implementation type of the subclass of TjbListener as return value of parameter, for example if you have
public U informAll2(T t){
for(U u:mListeners){
u.hearChange(t);
if (...)
return u;
}
}
In this case your declaration with two generic types is correct (just I'm not sure if it is possible to declare the generic U, which depends of T, before you declare T, of if you have to declare T first, like public abstract class ListenerInformer<T, U extends TjbListener<T>> )

Categories

Resources