How to use class instead of interface for lambda param - java

Right now I have this:
public static interface AsyncCallback<T, E> {
public void done(E e, T v);
}
I want to convert it to this so I use a boolean property on it:
public abstract static class AsyncCallback<T, E> {
boolean shortcircuit = false;
public abstract void done(E e, T v);
}
but now I am getting errors:
Inconvertible types; cannot cast '' to 'E'
and
no instance(s) of type variable(s) T exist so that List conforms to
AsyncTask
the code I have that generates the errors is based off passing lambdas. Does anyone know why converting the interface to a class causes problems? Even if I comment out the shortcircuit field and just have the done method definition, same errors arise.

You cannot use class instead of Interface ( Precisely to say Fuctional Interface).
See the link to know why do we need functional Interface to work with lambda in java.
In your case you are trying to use a class , which will obviously have
name, isn't. but to use lambda we have to use anonymous functions
which don't have name and type.

I solved this problem by keeping the interface but also using a class:
public static interface AsyncTask<T, E> {
public void run(AsyncCallback<T, E> cb);
}
public static interface IAsyncCallback<T, E> {
public void done(E e, T v);
}
public static abstract class AsyncCallback<T, E> implements IAsyncCallback<T, E> {
public boolean shortcircuit = false;
}
in circumstances where I must use an interface, I use the IAsyncCallback interface, where I can use a class, I use AsyncCallback class.

Related

How to satisfy parameter type Class<? extends someInterface> in java

Consider the following code
#Test
public void testFunction() {
// This cause error
callDoSomething(new myInterfaceImpl());
}
public interface myInterface {
int doSomething();
}
public class myInterfaceImpl implements myInterface {
public int doSomething() {
return 1;
}
}
public void callDoSomething(Class<? extends myInterface> myVar) {
System.out.println(myVar.doSomething());
}
On this line callDoSomething(new myInterfaceImpl()); I get the following error.
Error:(32, 25) java: incompatible types: com.myProject.myTest.myInterfaceImpl
cannot be converted to java.lang.Class<? extends com.myProject.myTest.myInterface>
How do I satisfy the parameter type? If only an interface is provided to me.
I want to bound the class that has an interface, but it seems like this is not avaiable to me
Class<? implements myInterace>
Edit:
The reason I want to do this is because I want to provide a custom kafka partitioner.
public Builder<K, V> withCustomPartitionner(Class<? extends Partitioner> customPartitioner) {
this.customPartitioner = customPartitioner;
return this;
}
It looks like you want to be able to call methods on the parameter that's given. In that case, you'll want the actual instance of your interface, not the Class associated with it.
public void callDoSomething(myInterface myVar) {
System.out.println(myVar.doSomething());
}
Class<> is used when you want to use reflection to do something with the specific class type that you're interested in:
public void outputClassInfo(Class<? extends myInterface> myClass) {
System.out.println(myClass.getName());
}
If that's what you're going for, you'll want to provide the class at compile time like this:
outputClassInfo(myInterfaceImpl.class);
Or, if you won't know which class you're dealing with until runtime, you can use reflection:
myInterface thing = getThing();
outputClassInfo(thing.getClass());
So, in the example you're providing in your edit, I'm guessing you want:
public Builder<K, V> withCustomPartitioner(Class<? extends Partitioner> customPartitioner) {
this.customPartitioner = customPartitioner;
return this;
}
// Usage
builder
.withCustomPartitioner(FooPartitioner.class)
...
This type Class<? extends myInterface> myVar corresponds to a Class instance not to an instance of myInterface.
You generally don't pass a class as parameter (but for reflection purposes or to bypass generics erasures). So what you need as parameter is probably :
public void callDoSomething(myInterface myVar) {
System.out.println(myVar.doSomething());
}
That you could invoke :
#Test
public void testFunction() {
// This cause error
callDoSomething(new myInterfaceImpl());
}
The parameter to callDoSomething shouldn't be a class. It must be an instance of that class or it's subclass.
public <T extends myInterface> void callDoSomething(T myVar) {
System.out.println(myVar.doSomething());
}
On a side note, don't name Java classes/interfaces starting with lower case.
As rightly mentioned by Andy Turner#, there is no need to use a type parameter here and you can just refer to the type as myInterface
public void callDoSomething(myInterface myVar) {
System.out.println(myVar.doSomething());
}
You need to pass the Class not an instance.
callDoSomething(MyInterfaceImpl.class);

JAVA GENERICS ERROR: have the same erasure, yet neither overrides the other [duplicate]

This question already has answers here:
interface and a class. name clash: same erasure, yet neither overrides other
(3 answers)
Closed 5 years ago.
For fun I'm creating a sorting framework to better understand the various sorting algorithms. And, I'm trying to make it generic enough so that it can sort anything that implements an interface that extends the comparable interface. However, the java compiler isn't happy with me.
Here's my interface:
public interface Sorter<C extends Comparable<C>>
{
void sort(C[] comparables);
void sort(C[] comparables, Comparator<C> comparator);
}
And, here's my abstract class that implements that interface:
public abstract class AbstractSort<C extends Comparable<C>> implements Sorter
{
protected abstract void doSort(C[] comparables, Comparator<C> comparator);
final public void sort(C[] comparables)
{
sort(comparables, new Comparator<C>()
{
public int compare(C left, C right)
{
return left.compareTo(right);
}
});
}
final public void sort(C[] comparables, Comparator<C> comparator)
{
doSort(comparables, comparator);
}
}
And, here are the errors I'm getting:
java: name clash: sort(C[]) in AbstractSort and sort(java.lang.Comparable[]) in Sorter have the same erasure, yet neither overrides the other
Error:(25, 23) java: name clash: sort(C[],java.util.Comparator<C>) in AbstractSort and sort(java.lang.Comparable[],java.util.Comparator<java.lang.Comparable>) in Sorter have the same erasure, yet neither overrides the other
Thanks in advance for your help!
Try writing implements Sorter<C>. Without the type parameter, you use raw types, which disables certain aspects of generics for inherited methods. Specifically, with a raw super type, you only inherit erased method signatures. In your case, rather than inheriting the method sort(C[] comparables) your inherit a method sort(Comparable[] comparables), which you can only override with an identical signature.
By specifying Sorter<C> as the supertype, you inherit a method `sort(C[] comparables), which you can override with the identical signature.
Pitfalls such as this is why the Java Language Specification recommends that raw types should only be used for interfacing with non-generic legacy code, and requires compilers to emit a warning when raw types are used.
I figured it out. Thanks for trying to help!
public interface Sorter<C extends Comparable<? super C>>
{
void sort(C[] comparables);
void sort(C[] comparables, Comparator<C> comparator);
}
public abstract class AbstractSort<C extends Comparable<? super C>> implements Sorter<C>
{
protected abstract void concreteSort(C[] comparables, Comparator<C> comparator);
final public void sort(C[] comparables)
{
sort(comparables, new Comparator<C>()
{
public int compare(Comparable left, Comparable right)
{
return left.compareTo(right);
}
});
}
final public void sort(C[] comparables, Comparator<C> comparator)
{
concreteSort(comparables, comparator);
}
}
The problem is both class and interface has the void sort(C[]), and they are conflicting. Try adding the #Override notation to the class methods.
I would say you are over-engineering this problem. I would prefer the interface, then you can do
Sorter<SortableClass> sorter = new QuickSorter<SortableClass>();
It is simple, and it will get to the point.

Why do my generics not take a subclass?

I had a question about similar generics yesterday, and as solution I implemented a sort of self-reference in some classes, like this:
public interface Action { }
public interface Result { }
public interface Player<A extends Action, R extends Result, P extends Player<A, R, P>> {
default public void onPostAction(final P target, final A action, final R result) { }
}
abstract public class GesturePlayer<A extends Action, R extends Result, P extends GesturePlayer<A, R, P>> implements Player<A, R, P> { }
abstract public class RPSPlayer extends GesturePlayer<RPSGesture, RPSResult, RPSPlayer> { }
public class RPSHumanPlayer extends RPSPlayer {
#Override
public void onPostAction(final RPSHumanPlayer target, final RPSGesture gesture, final RPSResult result) { }
}
This code does not compile, hoewver I am unable to figure out why.
It does work if in the #Override I use RPSPlayer, however RPSHumanPlayer is simply a subclass of it, should it not work the same as the following?
List<T> list = new ArrayList<>();
Which also has the type definied as the superclass (List resp RPSPlayer), and the referenced object's type as the subclass (ArrayLast resp RPSHumanPlayer).
My aim with this question is to gather insight on how the generics exactly work, and I want to keep the method signature as it is defined in RPSHumanPlayer.
What I think I understand about generics:
T is a typed parameter, like List<String>, etc. Also able to use it for own classes and methods. This also captures all subclasses of T.
? captures all possible Objects. Used to ensure that something is generic and not raw.
? extends T capture a specific subclass of T.
This code is written on Java 8.
In order to achieve the desired method signature in RPSHumanPlayer, you will need to generify RPSPlayer like this:
abstract public class RPSPlayer<P extends RPSPlayer<P>> extends GesturePlayer<RPSGesture, RPSResult, P> { }
Then you can define:
public class RPSHumanPlayer extends RPSPlayer<RPSHumanPlayer>
In Java, parameter types are part of the method signature, so they can't be changed (not even subclassed). Since Java 5, you can use covariant return types, but that's as far as it goes.
Your problem boils down to this:
public interface Player {
default public void onPostAction(Player target) {}
}
public abstract class HumanPlayer implements Player {
#Override
public void onPostAction(HumanPlayer target) {}
}
This cannot work, because onPostAction(HumanPlayer) cannot override onPostAction(Player), because then what would happen if it was called with a Player that was not a HumanPlayer?

Dependencies between generic classes

I have the following Interfaces:
public interface Assembler<T, S> {
S assemble( T val);
}
public interface Slicer<T, V> {
V[] slice(T val);
}
I want to have an Assembler instance use a Slicer instance and call it’s slice(). I have the following:
public class MyAssembler<T, S> implements Assembler<T, S> {
private final Slicer<T, V> slicer;
//ctor
public MyAssembler() {
slicer = new MySlicer<T, V>();
}
#Override
public S assemble(T val) {
V[] v = mySlicer.slice(val);
}
This doesn’t compile because the V type is not known (cannot be resolved to a type) in MyAssembler. I cannot change the Assembler interface to be Assembler<T, S, V>. Is there another way I can define the dependency? This is not an issue with non generic classes. Even if a static factory method is used to get the reference to Slicer, the problem of unknown V would still exist. Any suggestions? If this cannot be done, can anyone recommend a different approach or design pattern that allows for an Assembler to call the Slicer's slice()?
Will Assembler always have Slicer as one of its two generics? If so, you only need to define one generic, and have the Slicer as a non-generic member variable.
If, however, the generic types may or may not be Slicer, you can implement special handling for when one of them is Slicer with reflection, especially if (v instanceof Slicer) and then casting to Slicer if true.
Since your S and V are generic, you can exchange them for any other type, even other generics. You can do:
public class MyAssembler<T, S> implements Assembler<T, S> {
private final Slicer<T, S> slicer;
public MyAssembler() {
slicer = new MySlicer<T, S>();
}
#Override
public S assemble(T val) {
S[] v = slicer.slice(val);
return v[0]; // for example
}
}
What I did is to define T and S as the same type. In my own implementation, I can do this without problems.
Reposting Sotirios Delimanolis' comment as the answer.
To allow for the use of V in MyAssembler, declare MyAssembler<T, S, V> extends Assembler<T, S>. To use it, instantiate with for ex: Assembler<Integer, Integer> asmblr = new MyAssembler<Integer, Integer, Integer>.
Inheritance will solve your problem instead of Composition in this case as shown below:
public class MyAssembler<T,S,V> extends MySlicer<T,V> implements Assembler<T,S> {
public MyAssembler() {
}
#Override
public S assemble(T val) {
V[] v = this.slice(val);
...
}
}

The correct way of extending an ArrayList and and implementing an interface using Generics

I need to implement an interface that has two generic type arguments and a method that takes one generic type as the argument and the other generic type as a return type. This is how I implemented it but I don't know if it's the right way.
public interface Evaluate<K, T>
{
T use(K k);
}
Also, I need to extend the Java's ArrayList and add methods to it such as map. The map() method needs to take one argument of type Evaluate and return a new list. I don't know if I should implement the interface and how to actually pass the argument in my method. This is my attempt so far:
public class Array<K, T> extends java.util.ArrayList<T> implements Evaluate<K,T>
{
public ArrayList<T> map(Evaluate f1)
{
}
}
Do it either:
public class Array<K, T> extends java.util.ArrayList<T> implements Evaluate<K,T> {
T use(K k) {
// implementation
}
public java.util.ArrayList<T> map() {
// use(K) somewhere here
}
}
or
public class Array<K, T> extends java.util.ArrayList<T> {
public java.util.ArrayList<T> map(Evaluate<K,T> evaluate) {
// use evaluate somewhere here
}
}
Your implementation does't have definition of T use(K) declared in interface - you can leave it unimplemented only in an abstract class or an interface extending another one. Also your argument is raw since you didn't write it like map(Evaluate<K,T> f1) (Java doesn't automatically substitute generic parameters).

Categories

Resources