Simulating function templates in Java - java

I'm trying to simulate something analogous to a function template in Java, in the sense that I have something like the following:
public interface MyFunctionTemplate<T> {
void doSomething(T thing);
}
public class MyIntegerFunctionTemplate extends MyFunctionTemplate<Integer> { ... }
public class MyStringFunctionTemplate extends MyFunctionTemplate<String> { ... }
It appears that I will need a central registry of some sort. Something like the following:
public class MyFunctionTemplateRegistry {
private static Map<Class<?>, MyFunctionTemplate<?>> registry;
public static <T> void register(Class<T> templateClass, MyFunctionTemplate<T> templateFunction);
public static void doSomething(Object thing);
}
What is the best way to design such a thing?

Well, it depends on what you want to achieve and whether the implementing class needs to know the type or not. To me, your suggestion seems overdesigned (too complex), but it is really hard to say without having more concrete information.
The reason I'm saying this, is that I don't like the fact that you want to implement two separate classes for your interface (one for each type). The strength of using generics is often in finding a way to implement it with one class using the generic type T.
Then again, I might have misunderstood your intentions here...
Anyway, as a simple example, if your function(s) are purely mathematical, something like getMax() and getMin(), then you surely don't need to know anything more about T than the fact that T is comparable with T.
Then you could end up with something like this:
public class FindExtremes<T extends Comparable<T>> {
T getMax(T a, T b) {
return a.compareTo(b) >= 0 ? a : b;
}
T getMin(T a, T b) {
return a.compareTo(b) <= 0 ? a : b;
}
}
This could the be used directly for any class that implements Comparable, e.g.
new FindExtremes<Integer>().getMax(4, 5);
new FindExtremes<Double>().getMax(4.444D, 5.555D);
new FindExtremes<String>().getMax("abc", "zyx");

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?

How can i make an interface in java with a function that accepts a parameter of the type that extends the interface?

How can i make an interface in java with a function that accepts a parameter of the type that extends the interface?
For example take the interface ISelfComparable
if class A extends it then i would expect it to implement
bool compareTo(A other)
but if class B extends it then i would expect it to implement
bool compareTo(B other)
I know i can use a generic interface but it seems incorrect because it doesn't make any sense for A to extend ISelfComparable<B>
If this is impossible, what is the best practice in this kind of situation?
The usual solution is self-bounded generics, as seen in the Enum class.
interface Example<T extends Example<T>> {
void foo(T t);
}
public class ExampleImpl implements Example<ExampleImpl> {
#Override
public void foo(ExampleImpl example) {
}
}
How it works is a bit dizzying, but is explained very well here for example. There is also a very good answer on the subject here.
Note that it isn't foolproof, as it allows this:
public class ExampleImpl2 extends Example<ExampleImpl {
#Override
public void foo(ExampleImpl example) {
}
}
But in practice the self-bounded idiom is used to express exactly the sort of thing you're after.
If you really, really, really need the parameter object to always be the exact same class as this, you have to do a runtime check. (It also raises the question of why you need this, but that would take us way off topic.)
Have a look at the class java.lang.Comparable: it has an argument with the type of the objects that can be used int compareTo.
By analogy:
public interface ISelfComparable<T extends ISelfComparable<T>> {
boolean compareTo(T other);
}
There is a way to check the type of parameter but only in runtime. For example you can implement type checking in default method:
interface ISelfComparable {
default boolean compareTo(ISelfComparable param) {
if (this.getClass() != param.getClass()) {
throw new IllegalArgumentException();
}
...
}
}
Then each implementation of this interface should look like this:
class A implements ISelfComparable {
#Override
public boolean compareTo(ISelfComparable param) {
ISelfComparable.super.compareTo(param);
...
}
}
In this case if you call new A().compareTo(new B()); then java.lang.IllegalArgumentException will be thrown

Can I define the Negatable interface in Java?

Asking this question to clarify my understanding of type classes and higher kinded types, I'm not looking for workarounds in Java.
In Haskell, I could write something like
class Negatable t where
negate :: t -> t
normalize :: (Negatable t) => t -> t
normalize x = negate (negate x)
Then assuming Bool has an instance of Negatable,
v :: Bool
v = normalize True
And everything works fine.
In Java, it does not seem possible to declare a proper Negatable interface. We could write:
interface Negatable {
Negatable negate();
}
Negatable normalize(Negatable a) {
a.negate().negate();
}
But then, unlike in Haskell, the following would not compile without a cast (assume MyBoolean implements Negatable):
MyBoolean val = normalize(new MyBoolean()); // does not compile; val is a Negatable, not a MyBoolean
Is there a way to refer to the implementing type in a Java interface, or is this a fundamental limitation of the Java type system? If it is a limitation, is it related to higher-kinded type support? I think not: it looks like this is another sort of limitation. If so, does it have a name?
Thanks, and please let me know if the question is unclear!
Actually, yes. Not directly, but you can do it. Simply include a generic parameter and then derive from the generic type.
public interface Negatable<T> {
T negate();
}
public static <T extends Negatable<T>> T normalize(T a) {
return a.negate().negate();
}
You would implement this interface like so
public static class MyBoolean implements Negatable<MyBoolean> {
public boolean a;
public MyBoolean(boolean a) {
this.a = a;
}
#Override
public MyBoolean negate() {
return new MyBoolean(!this.a);
}
}
In fact, the Java standard library uses this exact trick to implement Comparable.
public interface Comparable<T> {
int compareTo(T o);
}
In general, no.
You can use tricks (as suggested in the other answers) that will make this work, but they do not provide all of the same guarantees that the Haskell typeclass does. Specifically, in Haskell, I could define a function like this:
doublyNegate :: Negatable t => t -> t
doublyNegate v = negate (negate v)
It is now known that the argument and return value of doublyNegate are both t. But the Java equivalent:
public <T extends Negatable<T>> T doublyNegate (Negatable<T> v)
{
return v.negate().negate();
}
doesn't, because Negatable<T> could be implemented by another type:
public class X implements Negatable<SomeNegatableClass> {
public SomeNegatableClass negate () { return new SomeNegatableClass(); }
public static void main (String[] args) {
new X().negate().negate(); // results in a SomeNegatableClass, not an X
}
This isn't particularly serious for this application, but does cause trouble for other Haskell typeclasses, e.g. Equatable. There is no way of implementing a Java Equatable typeclass without using an additional object and sending an instance of that object around wherever we send values that need comparing, (e.g:
public interface Equatable<T> {
boolean equal (T a, T b);
}
public class MyClass
{
String str;
public static class MyClassEquatable implements Equatable<MyClass>
{
public boolean equal (MyClass a, MyClass b) {
return a.str.equals(b.str);
}
}
}
...
public <T> methodThatNeedsToEquateThings (T a, T b, Equatable<T> eq)
{
if (eq.equal (a, b)) { System.out.println ("they're equal!"); }
}
(In fact, this is exactly how Haskell implements type classes, but it hides the parameter passing from you so you don't need to figure out which implementation to send where)
Trying to do this with just plain Java interfaces leads to some counterintuitive results:
public interface Equatable<T extends Equatable<T>>
{
boolean equalTo (T other);
}
public MyClass implements Equatable<MyClass>
{
String str;
public boolean equalTo (MyClass other)
{
return str.equals(other.str);
}
}
public Another implements Equatable<MyClass>
{
public boolean equalTo (MyClass other)
{
return true;
}
}
....
MyClass a = ....;
Another b = ....;
if (b.equalTo(a))
assertTrue (a.equalTo(b));
....
You'd expect, due to the fact that equalTo really ought to be defined symmetrically, that if the if statement there compiles, the assertion would also compile, but it doesn't, because MyClass isn't equatable with Another even though the other way around is true. But with a Haskell Equatable type class, we know that if areEqual a b works, then areEqual b a is also valid. [1]
Another limitation of interfaces versus type classes is that a type class can provide a means of creating a value which implements the type class without having an existing value (e.g. the return operator for Monad), whereas for an interface you must already have an object of the type in order to be able to invoke its methods.
You ask whether there is a name for this limitation, but I'm not aware of one. It's simply because type classes are actually different to object-oriented interfaces, despite their similarities, because they are implemented in this fundamentally different way: an object is a subtype of its interface, thus carries around a copy of the interface's methods directly without modifying their definition, while a type class is a separate list of functions each of which is customised by substituting type variables. There is no subtype relationship between a type and a type class that has an instance for the type (a Haskell Integer isn't a subtype of Comparable, for example: there simply exists a Comparable instance that can be passed around whenever a function needs to be able to compare its parameters and those parameters happen to be Integers).
[1]: The Haskell == operator is actually implemented using a type class, Eq ... I haven't used this because operator overloading in Haskell can be confusing to people not familiar with reading Haskell code.
I interpret the question as
How can we implement ad-hoc polymorphism using typeclasses in Java?
You can do something very similar in Java, but without the type safety guarantees of Haskell - the solution presented below can throw errors at runtime.
Here is how you can do it:
Define interface that represents the typeclass
interface Negatable<T> {
T negate(T t);
}
Implement some mechanism that allows you to register instances of the typeclass for various types. Here, a static HashMap will do:
static HashMap<Class<?>, Negatable<?>> instances = new HashMap<>();
static <T> void registerInstance(Class<T> clazz, Negatable<T> inst) {
instances.put(clazz, inst);
}
#SuppressWarnings("unchecked")
static <T> Negatable<T> getInstance(Class<?> clazz) {
return (Negatable<T>)instances.get(clazz);
}
Define the normalize method that uses the above mechanism to get the appropriate instance based on the runtime class of the passed object:
public static <T> T normalize(T t) {
Negatable<T> inst = Negatable.<T>getInstance(t.getClass());
return inst.negate(inst.negate(t));
}
Register actual instances for various classes:
Negatable.registerInstance(Boolean.class, new Negatable<Boolean>() {
public Boolean negate(Boolean b) {
return !b;
}
});
Negatable.registerInstance(Integer.class, new Negatable<Integer>() {
public Integer negate(Integer i) {
return -i;
}
});
Use it!
System.out.println(normalize(false)); // Boolean `false`
System.out.println(normalize(42)); // Integer `42`
The main drawback is that, as already mentioned, the typeclass instance lookup can fail at runtime, not at compile-time (as in Haskell). Using a static hash map is suboptimal too, because it brings all the problems of a shared global variable, this could be mitigated with more sophisticated dependency injection mechanisms. Automatically generating typeclass instances from other typeclass instances, would require even more infrastructure (could be done in a library). But in principle, it implements ad-hoc polymorphism using typeclasses in Java.
Full code:
import java.util.HashMap;
class TypeclassInJava {
static interface Negatable<T> {
T negate(T t);
static HashMap<Class<?>, Negatable<?>> instances = new HashMap<>();
static <T> void registerInstance(Class<T> clazz, Negatable<T> inst) {
instances.put(clazz, inst);
}
#SuppressWarnings("unchecked")
static <T> Negatable<T> getInstance(Class<?> clazz) {
return (Negatable<T>)instances.get(clazz);
}
}
public static <T> T normalize(T t) {
Negatable<T> inst = Negatable.<T>getInstance(t.getClass());
return inst.negate(inst.negate(t));
}
static {
Negatable.registerInstance(Boolean.class, new Negatable<Boolean>() {
public Boolean negate(Boolean b) {
return !b;
}
});
Negatable.registerInstance(Integer.class, new Negatable<Integer>() {
public Integer negate(Integer i) {
return -i;
}
});
}
public static void main(String[] args) {
System.out.println(normalize(false));
System.out.println(normalize(42));
}
}
You're looking for generics, plus self typing. Self typing is the notion of generic placeholder that equates to the class of the instance.
However, self typing doesn't exist in java.
You can get close with generics, but it's clunky:
public interface Negatable<T> {
public T negate();
}
Then
public class MyBoolean implements Negatable<MyBoolean>{
#Override
public MyBoolean negate() {
//your impl
}
}
Some implications for implementers:
They must specify themselves when they implement the interface, e.g. MyBoolean implements Negatable<MyBoolean>
Extending MyBoolean would require one to override the negate method again.

Java generics and streams

I'm building a sort of framework to avoid repetition of code, and at a certain point I need to convert a list of object Foo into a list of object Bar.
I have database entities that extend
public class BaseEntity {...}
And presentation objects that extend
public class BaseDTO<T extends BaseEntity> {...}
so
public class Foo extends BaseEntity {...}
and
public class Bar extends BaseDTO<A extends BaseEntity> {
public Bar(Foo entity, Locale l) {
...
}
}
Now to convert a list of Foo into a list of Bar is easy using streams
public abstract ClassThatUsesFooAndBar() {
public List<Bar> convertFooToBar(List<Foo> list) {
return list.stream().map(f -> new Bar(f, locale)).collect(...);
}
}
But, and here is the question, these Foo and Bar are actually generics (A and B), so the class that uses Foo and Bar actually is ClassThatUsesAandB<A extends BaseEntity, B extends BaseDTO>, so that function must be abstract too and implemented as boilerplate code with the correct A and B implementations because obviously you cannot instantiate generic types.
Is there a way to use generics/streams/lambdas to create a function that can be written once, so that the implementing classes don't need to re-implement it? The function signature would be
public List<B> convertAToB(List<A> list);
I hope I've been clear enough in what I need, if you need further explanations please ask
Thank you!
I think the simplest way is to use lambdas for the conversion.
public static <A,B> List<B> convertList(List<A> list, Function<A,B> itemConverter) {
return list.stream().map(f -> itemConverter.apply(f)).collect(...);
}
And then you can use it like this:
List<Bar> l = convertList(fooList,foo -> new Bar(foo.getBaz()));
Or if you want to, you can extract it in its own named class:
public class Foo2BarConverter implements Function<Foo,Bar> {
#Override
public Bar apply(Foo f) {
return new Bar(f.getBaz());
}
}
As an aside, given what we can do with streaming, it seems like a bit of a waste to create a new list just to have a materialised list of Bar objects. I would probably chain whatever operation I want to do with the list straight after the conversion.
The most difficult problem with your question is actually not the boilerplate or the streams, it's the generics. Trying to do new B is a bit of a mess. You can't do it directly, and any workaround isn't too clean.
For the boilerplate, however, you can do a bit better thanks to Java 8's default methods in interface. Consider the following interface:
public interface ConversionHandler<A,B> {
B constructB(A a, Locale locale);
default List<B> convertAToB(List<A> list, Locale locale) {
return list.stream().map(a -> constructB(a, locale)).collect(Collectors.toCollection(ArrayList::new));
}
}
The list conversion boilerplate is now done, all you have to do is implement the B construction in the subclass. However, this is still tricky if B is still generic.
public class ClassThatUsesAandB<A, B> implements ConversionHandler<A,B> {
#Override
public B constructB(A a, Locale locale) {
return null; //This is tricky
}
}
However, if the subclass is concrete, it's quite simple
public class ConverterClass implements ConversionHandler<String,Integer> {
#Override
public Integer constructB(String s, Locale locale) {
return s.length();
}
}
So the followup you may want to search for is a good design pattern for making the construction of generic objects as maintainable and readable as possible.

Java design issue - Adding functionality to fixed classes

I have a set of classes that all need to be acted on in some (individual) way.
Ordinarily I'd just create a DoSomethingInterface with a single doSomething() method and have each class implement that method in a way that suits each class' needs. However, I cannot do that in this case as the class definitions are unmodifyable (auto-generated)
So, I reckon I need to create a set of different classes that each take one of the autogenerated classes and performs the operation on them. So, say I have 2 autogenerated classes, Class1 and Class2, I will first define a common Operator interface:
public interface Operator <TYPE>{
public void doSomething(TYPE type);
}
and then implement one of these per class
public class Class1Operator implements Operator<Class1>{
public void doSomething(Class1 type){
...
...
}
}
and
public class Class2Operator implements Operator<Class2>{
public void doSomething(Class2 type){
...
...
}
}
Ok, so far so good. Now, given that I have an object of type Class1, is there any way of getting its operator without resorting to:
public Operator getOperator(Object obj){
if(obj instanceof Class1){
return new Class1Operator();
}else if(obj instanceof Class2{
return new Class2Operator();
}
return null;
}
Which kinda seems like bad practice to me...
The only other way I can think of is by creating a map of operators to class names like so:
Map<Class, Operator> allOperators = new HashMap<Class, Operator>();
allOperators.put(Class1.class, new Class1Operator());
allOperators.put(Class2.class, new Class2Operator());
and then return the operator using:
public Operator getOperator(Object obj){
return allOperators.get(obj);
}
But this doesn't seem right (I'm not sure, are there any issues with keying an object off its class....)
Any input as to whether either of these approaches is 'correct'? or is there a more elegant solution??
Thanks
What you've implemented (the map-by-class approach) is one of the alternatives to the GoF Visitor pattern I talk about when I teach patterns. It's efficient and extendable, even at runtime. Much better than the if/else if/else hardwired approach.
The only issue with keying off the class is if the actual instances implement subtypes rather than the class type you mention; then the lookup map won't work.
If you need subtypes to be recognized, I'd recommend Aaron's approach (walk up the superclass chain), but you may also want to look at implemented interfaces as well. If you just need "exact class match", keep your getOperator simple.
Note that you have a bug in getOperator -- it should look as follows:
public Operator getOperator(Object obj){
return allOperators.get(obj.getClass());
}
One more thing... Hide your map inside another class and manage it as follows:
private Map<Class<?>, Operator<?>> map = new HashMap<Class<?>, Operator<?>>();
public <T> void register(Class<T> clazz, Operator<T> operator) {
map.put(clazz, operator);
}
This prevents anyone from registering an operator that won't work against the class it's keyed against. (You might want to use Operator as the parameter to allow an operator that's written against a superclass, but that's might not be needed)
One of the issues with building a map is that it will not support subclasses unless you register them specifically or extend your get function to look up super classes specifically.
That is to say if B inherits from A and you've registered an operator with A.class. Fetching an operator with B.class will fail, unless you change your getOperator to something like:
public Operator getOperator(Object obj){
Class<?> current = obj.getClass();
Operator op;
while((op = allOperators.get(current)) == null){
current = current.getSuperclass();
if(current == null){
/*
* We've walked all the way up the inheritance hierarcy
* and haven't found a handler.
*/
return null;
}
}
return op;
}
Once you've got a reasonable getOperator implementation, mapping classes to operators seems like a reasonable approach.
You can us Class.isAssignableFrom to get around the sub-typing issue. I use this all the time and while it is not "visitor" elegant it is quite fine in practice.
Would it be possible to create your own class that extends the generated class and then have your class implement the interface?
Have you considered this:
public Interface Operator {
public void doSomething();
}
public class Class1Operator extends Class1 implements Operator {
...
}
public class Class2Operator extends Class2 implements Operator {
...
}
But with reference to your second question of getting an operator to an object without really needing to do the "instanceof" mojo (I guess that's what is looking unclean):
I would suggest that if you can't modify your classes to your exact needs, write a wrapper around them:
public Interface Operator<T> {
public void doSomething(T obj);
}
public Interface WrappedObject<T> {
public Operator<T> getOperator();
}
public class WrappedClass1 extends Class1 implements WrappedObject<Class1> {
...
}
public class WrappedClass2 extends Class2 implements WrappedObject<Class2> {
...
}
public class Class1Operator implements Operator<Class1> {
...
}
public class Class2Operator implements Operator<Class2> {
...
}
Would that suffice your needs?
Its always a good practice to write wrappers around classes that don't match your needs perfectly, and can't be controlled by you. It helps you keep your code healthy even if these wild classes change.
Cheers,
jrh.
I'm going to say it's not possible to do just using the interface itself, based on the way Java handles generics.
In Java, generics are erased at compile time and replaced with casts.
I haven't actually checked how it works internally, but at a guess, your interface turns into this:
public interface Operator {
public void doSomething(Object type);
}
and where it's called, into this:
public class Class1Operator implements Operator{
public void doSomething(Object type){
Class1 oType = (Class1) type;
...
...
}
}
This still isn't exactly right as type will be cast after it's returned as well, plus Java bytecode doesn't actually look like Java, but you might get the general idea.
The instanceof and Map methods should work, even if they are a bit messy.

Categories

Resources