Narrow down the scope of generic super-interface in implementing classes - java

Providing I have an interface like:
public interface Replicateable<T> {
void replicate(T entity);
}
another one extending it
// here Identifiable is just another interface
public interface Entity extends Identifiable, Replicateable<Entity> {
//some declarations here
}
and in the end of this chain I'd like to have something like
public class ConcreteEntity implements Entity {
#Override
public void replicate(ConcreteEntity entity) {
// here goes some logic turning current entity
// to a replica of a passed one
}
}
Any ways to achieve that besides making the Entity interface generic? I'd rather avoid that.
So for I tried to
1. Leave as it is, which doesn't work since replicate() implementation requires exactly an Entity parameter, and not a concrete one
2. Add Replicateable right to entity class
public class ConcreteEntity implements Entity, Replicateable<ConcreteEntity> { ... }
which gave me 'Replicateable' cannot be inherited with different type arguments: 'Entity' and 'ConcreteEntity' (and it seems understandable why it didn't work).
3. Override replicate() in the Entity interface (with no results either, not even sure if it's meaningful at all).
4. Make a replicate() generic instead of Replicateable itself (not sure how to make it right)
Would appreciate any suggestions how to make it right.

Entity would have to be generic for the compiler to know which type can be passed to replicate:
Entity<ConcreteEntity> e = ...;
e.replicate(...); // <-- aha. Can only pass a ConcreteEntity (or a subtype of)
It might make more sense to use polymorphism:
interface Replicateable<T> {
T replicate();
}
interface Entity extends Identifiable, Replicateable<Entity> {
// Entity replicate();
}
Which could be implemented using copy constructors:
class ConcreteEntity implements Entity {
public ConcreteEntity(ConcreteEntity other) {...}
#Override
public ConcreteEntity replicate() { // <-- uses return type overriding
return new ConcreteEntity(this);
}
}
Entity e1 = new ConcreteEntity();
Entity copy1 = e1.replicate();
ConcreteEntity e2 = new ConcreteEntity();
ConcreteEntity copy2 = e2.replicate();

What you are trying to do requires making Entity generic due to the way Generics work in Java. It is a strange pattern but it comes up from time to time.
public interface Entity<T extends Entity> extends Identifiable, Replicateable<T> {
//some declarations here
}
public class ConcreteEntity implements Entity<ConcreteEntity> {
#Override
public void replicate(ConcreteEntity entity) {
// here goes some logic turning current entity
// to a replica of a passed one
}
}
However there may be a different way of designing your interfaces so that this is not required. What are you trying to do with replicate?
Your comments make it sound like you would do the following.
SomeEntity a = new SomeEntity();
// set values on a
SomeEntity b = new SomeEntity();
b.replicate(a);
IF that is what you are trying to do there several other ways to achieve that end result
SomeEntity a = new SomeEntity();
// set values on a
SomeEntity b = new SomeEntity(a); // copy constructor
SomeEntity c = a.clone(); // Clone operation
See the PrototypePattern for a more in depth overview of creating objects based upon the values of other objects.

It's not possible without making Entity also generic. You should use F-bounded types:
F-bounded quantification or recursively bounded quantification, introduced in 1989, allows for more precise typing of functions that are applied on recursive types. A recursive type is one that includes a function that uses it as a type for some argument or its return value.
In Java, F-bounded types can be expressed with a generic interface, which in your case would be as follows:
public interface Replicateable<T extends Replicateable<T>> {
void replicate(T entity);
}
public interface Entity<T extends Entity<T>> extends Replicateable<T> {
//some declarations here
}
public class ConcreteEntity implements Entity<ConcreteEntity> {
#Override
public void replicate(ConcreteEntity entity) {
// here goes some logic turning current entity
// to a replica of a passed one
}
}

Thanks everyone for your answers, they were insightful and helped me to come up with a suitable solution.
I ended up redefining replicateable interface to
public interface Replicateable<T> {
//note the boolean return type here
boolean replicate(T entity);
}
leaving it as it was in the entity interface, without making it generic
public interface Entity extends Identifiable, Replicateable<Entity> {
//some declarations here
}
which allows to not to rewrite tons of code to get rid of raw-types and doesn't break entity's generic method implementations (why it's being broken upon making Entity itself is another question out of the scope of this one.)
An the method implementation looks like
#Override
public boolean replicate(Entity entity) {
if (entity.getClass() == ConcreteEntity.class) {
// replicating logic
return true;
}
return false;
}
This method doesn't create a new object by turns an existing one to a replica of one that was passed to the method, that was the point (I should've mentioned it, my apologies for that). Otherwise I'd use Cloneable, as per some of your suggestions.
So, to sum up and generalize - it's either make Entity generic or to use Cloneable (both not my cases) or to invent a workaround, which I did. Thanks again everyone.

Related

JDBI3 Returning a Parameterized Class

I have an abstract EntryPoint class that looks like this:
public abstract class EntryPoint<T extends Tag> implements Serializable {
public EntryPoint(){}
protected ArrayList<T> tiedTags;
public abstract ArrayList<T> getTiedTags();
public abstract void setTiedTags(List<T> tiedTags);
}
I then have subclasses of this EntryPoint class that each accept only one kind of Tag. For instance an SNMPEntryPoint only stores SNMPTags. The subclasses provide implementations of the abstract methods:
public class SNMPEntryPoint extends EntryPoint<SNMPTag> implements Serializable {
//Default Constructor for Serialization
public SNMPEntryPoint(){}
#Override
public ArrayList<SNMPTag> getTiedTags(){ return tiedTags; }
//etc
}
Is there a means to create a JDBI query that returns a List of parameterized classes? At the moment, this is what I'm doing:
public List<SNMPEntryPoint> getSNMPEntryPoints(){
try(Handle handle = daoFactory.getDataSourceController().open()) {
return handle.createQuery("SELECT * FROM dbo.EntryPoints WHERE Active = 1 AND SiteID = :sID AND Protocol = 'SNMP'")
.mapToBean(SNMPEntryPoint.class)
.list();
}
catch(Exception e){
if(sysconfig.getVerbose()){ e.printStackTrace(); }
}
return null;
}
But this feels like a raw use of the class. So I guess my question is, if I use this code to generate SNMPEntryPoints and then call getTiedTags or setTiedTags on those EntryPoints, will that work? Am I breaking any coding conventions by creating my SNMPEntryPoint objects in this way?
Just wanted to close this out. My classes weren't actually parameterized. As you can see above they extend the parameterized abstract class however SNMPEntryPoint doesn't actually take any parameters, so there's no need to do anything differently from what I'm doing above.
HOWEVER, if you do need to return a parameterized generic from JDBI you can do so using the details found here.

Why isn't there a way for an interface to require implementing classes to reference their own type?

Interfaces like Comparable<> use generics to establish which type a class is comparable to. In some cases, it may make sense to have one class comparable to another such as A implements Comparable<B>. But I'm working through a situation now where I would like the interface to specify that the return type is always the same as the type implementing the interface. That is to say, the type of A.get() should always be A.
My original attempt to force self-reference looked like:
interface Property<T extends Property<T>> {
public T get();
}
This allows
class A implements Property<A> {
public A get() { ... }
}
while preventing things like
class A implements Property<B> {
public B get() { ... }
}
Unfortunately, it allows the following to compile:
class A implements Property<A> {
public A get() { ... }
}
class B implements Property<A> {
public A get() { ... }
}
Is there a way to do this?
No, there is no way to force a subclass to narrow a return type on an inherited method based on the generic type parameter of the Curiously Recurring Template Pattern. You cannot force B to have get() return B. It's an object-oriented principle that a subclass can inherit a method without changing anything about it.
Sometimes I've wished for this feature -- a generic "relationship to self" type. Here's how I would have the syntax. The keyword "this" would represent this type - A in A, B in B.
public class A {
public this get() {
return this; // Or another instance of this type
}
}
public class B extends A {
// "this" on get in A forces B to override "get"
// to narrow the return type
#Override
public this get() {
return this;
}
}
But forcing B to override getA() goes against object-oriented principles. The subclass should be free to inherit a method from a superclass as-is.

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.

Generics, Interface puzzle, what is the advantage of declaring interface like this?

In my project I see the interface like this. All the model extend the interface. I am wondering what is the use ?
public interface IModel {
<T> T modelTo(Class<T> clazz);
}
public interface IPerson extends IModel {
public String getFirstName();
public void setFirstName(String firstName);
public String getMiddleName();
public void setMiddleName(String middleName);
}
Then in some places in the code I see like
#Override
public void modelJoin(IModel parent, IModel sample) {
//Some code
IPerson sample= sample.modelTo(IPerson.class);
IPerson person = parent.modelTo(IPerson.class);
//Some code
}
Can you explain me the insight of it ?
It looks like the use of the Adapter pattern. The idea is to create a "view" of a class given another class, or adapt one type of class to act as another.
A simple real world example can be that of electrical sockets. In different countries different types of sockets are used. So you use adapters to plug in your phone into an electrical socket it normally doesn't "recognize".
This can of course be modelled using object oriented programming and the adapter pattern as well. Using your IModel interface but naming it IAdaptable it could be used like this.
public interface IAdaptable {
<T> T adaptAs(Class<T> clazz);
}
public interface IChargeAmerican { void chargePhoneInAmerica(); }
public interface IChargeEurope { void chargePhoneInEurope(); }
public class EuropeanSocket implements IAdaptable, IChargeEurope {
public <T> T adaptAs(Class<T> clazz) {
if (clazz.equals(IChargeAmerican.class)) {
return new EuropeanSocketToAmericanSocketAdapter(this);
}
throw new RuntimeException("unknown");
}
public void chargePhoneInEurope() {
;
}
}
public class AmericanSocket implements IChargeAmerican {
public void chargePhoneInAmerica() {
;
}
}
public class EuropeanSocketToAmericanSocketAdapter implements IChargeAmerican {
private EuropeanSocket socket;
public EuropeanSocketToAmericanSocketAdapter(EuropeanSocket socket) {
this.socket = socket;
}
public void chargePhoneInAmerica() {
socket.chargePhoneInEurope();
}
}
And to use it one would simply adapt the european socket to an american one, sort of like plugging in an adapter in between the two.
public void foo() {
EuropeanSocket europe = new EuropeanSocket();
IChargeAmerican murica = europe.adaptAs(IChargeAmerican.class);
murica.chargePhoneInAmerica();
}
This example shows how the adaptAs method creates a link between the two interfaces IChargeAmerican and IChargeEurope. Even though they don't have anything in common the adapter can act as they do.
Now, the EuropeanSocket implements the IAdaptable interface in order to "convert" itself to another known socket. Usually though the class should not be responsible for this. As the example at wikipedia shows, a factory or provider is better suited for this.
I think that you ask why the method signature
<T> T modelTo(Class<T> clazz);
is used.
The parameter clazz is used to have the type information inside the method implemented. You can then access the type information very easy.
You can then create an object and return it from the implemented method that has the given class.
The method signature looks a bit clumsy but is helpful as the generic information is missing after compilation (type erasure) and the parameters give you the possibility to access the type information (and thereforethe expected return type).
I can imagine it may have been made that way to allow type casting by passing a Class object as a parameter of other methods calling the modelTo(Class clazz) method, or in other words : having other methods casting IModel objects to any class without even knowing which class they will cast it into (nothing even prevents from passing a Class instance to this method which isn't even a subtype of IModel...)
It would be interesting to know how this modelTo method is implemented. Is there a single, final implementation in an abstract skeleton class ? How does it respond to errors (like passing null as the clazz parameter, or triggering a ClassCastException) ? In other words : could this be an attempt to encapsulate all class casts into a single method, to replace ClassCastExceptions with a custom Exception or something like that ? (ClassCastException being a RuntimeException, it could have been a way to make sure a checked exception is thrown instead to enforce explicit exception handling everywhere in the code, I've already seen projects using such an approach...)

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