Double-nested Java generics - java

I asked a similar question this morning, thought I had it answered, actually implemented the proposed solution, and it failed to do what I need. So here's my full problem:
I have the following classes:
// Objects to process.
public class Apple {
private Color color;
private int numberOfSeeds;
// ...
}
public class Chair {
private Material madeOutOfMaterial;
private double price;
// ...
}
public class CellPhone {
private Manufacturer make;
private String model;
private boolean isSmartPhone;
// ...
}
// Contains the object that will be processed (an Apple, Chair, CellPhone instance, etc.)
// as well as metadata info about the processing itself (timestamp, a UUID for tracking
// purposes, etc.).
public class ProcessingMetadata<PROCESSABLE_OBJECT> {
private PROCESSABLE_OBJECT result;
private Date processedOnDate;
private String uuid;
// ...
}
// Abstract base class for processing PROCESSABLE_OBJECTs.
public abstract class ObjectProcessor<ProcessingMetadata<PROCESSABLE_OBJECT>> {
private String name;
public abstract ProcessingMetadata<PROCESSABLE_OBJECT> process(Data data);
}
// One concrete processor.
public class SimpleObjectProcessor extends ObjectProcessor<ProcessingMetadata<PROCESSABLE_OBJECT>> {
private Fizz fizz;
#Override
public ProcessingMetadata<PROCESSABLE_OBJECT> process(Data data) {
// Processes data one way, and returns a PROCESSABLE_OBJECT.
}
}
// Another concrete processor.
public class ComplexObjectProcessor extends ObjectProcessor<ProcessingMetadata<PROCESSABLE_OBJECT>> {
private Buzz buzz;
#Override
public ProcessingMetadata<PROCESSABLE_OBJECT> process(Data data) {
// Processes data differently, and returns a PROCESSABLE_OBJECT.
}
}
So that the final code, using all of these classes looks like this:
ObjectProcessor<ProcessingMetadata<Apple>> appleProcessor =
new ComplexObjectProcessor<ProcessingMetadata<Apple>>();
Data data = getData();
ProcessingMetadata<PROCESSABLE_OBJECT> meta = appleProcessor.process(data);
Apple apple = meta.getResult();
Date processedOn = meta.getProcessedOnDate();
String uuid = meta.getUUID();
This is the "API" that I want exposed to the developer. Grab some Data, select a typed processor, process the data, and get all the metadata you need.
The problem is that my ObjectProcessor<ProcessingMetadata<PROCESSABLE_OBJECT>> isn't legal. It gives me the following compiler error on the ProcessingMetadata portion of the class definition:
Syntax error on token(s), misplaced construct(s)
I have played with this class (and its concrete subclasses) all morning, and can't seem to get generics set up correctly to give me the API that I want. I'm open to requiring the PROCESSABLE_OBJECTs to actually being an interface, such as Processable, and having Apple, Chair, etc. implement it. But there's no telling what the client is going to want to process, and so I'd prefer not to force them to make their POJOs implement a Processabl interface, if at all possible.
So, is my desired API possible? If so, how? If not, then why, and what is the closest I can get to it? Thanks in advance!

Each of the items in the type parameter list needs to be a type parameter. In the class declaration of ObjectProcessor, ProcessingMetadata<PROCESSABLE_OBJECT> is not a generic type parameter.
You could specify PROCESSABLE_OBJECT as a parameterized type, and then specify a type extending ProcessingMetaData as another parameterized type.
public abstract class ObjectProcessor<
PROCESSING_METADATA extends ProcessingMetadata<PROCESSABLE_OBJECT>,
PROCESSABLE_OBJECT >
{ ... }
EDIT:
Your subclasses are also parameterized types. You need to declare those type parameters on the class itself. Then you can use them to parameterize the superclass.
public class SimpleObjectProcessor<
PROCESSING_METADATA extends ProcessingMetadata<PROCESSABLE_OBJECT>,
PROCESSABLE_OBJECT >
extends ObjectProcessor< PROCESSING_METADATA,PROCESSABLE_OBJECT >
{ ... }

I think in your api, the developer would use this line
ProcessingMetadata<PROCESSABLE_OBJECT> meta = appleProcessor.process(data);
as this
ProcessingMetadata<Apple> meta = appleProcessor.process(data);

The class declaration itself only takes a type parameter declaration, but you try to put ProcessingMetadata there.
public abstract class ObjectProcessor<PROCESSABLE_OBJECT> {
private String name;
public abstract ProcessingMetadata<PROCESSABLE_OBJECT> process(Data data);
}
public class SimpleObjectProcessor<PROCESSABLE_OBJECT>
extends ObjectProcessor<PROCESSABLE_OBJECT> {
private Fizz fizz;
#Override
public ProcessingMetadata<PROCESSABLE_OBJECT> process(Data data) {
// Processes data one way, and returns a PROCESSABLE_OBJECT.
}
}
ObjectProcessor<Apple> appleProcessor = new ComplexObjectProcessor<Apple>();
// Note: there is no PROCESSABLE_OBJECT here. Use the concrete type:
ProcessingMetadata<Apple> meta = appleProcessor.process(data);

Related

How can I avoid an "Unchecked overriding" warning when interface method's generic return is implemented with a concrete type in Java?

This is an educational question that relates to a hobby project. Project Spring Boot MVC/REST app.
I would like to retain the flexibility to be able to create multiple implementations of Service and have list return a list of objects, depending on what the implementation requires.
I appreciate I could create some inheritance/implementation hierarchy to define the kinds of objects of which T could encompass. My problem with both of those answers is that some use cases for Service involve me needing to return Lists of Java Standard Lib types - types I would rather not inherit/extend/implement for my own custom classes, which I would prefer be kept as lean as possible.
import java.util.List;
interface Service {
<T> List<T> list(String location, MyEnums.mediaType type );
}
class MyEnums {
enum mediaType {
IMAGE, VIDEO, AUDIO
}
}
class LocalService implements Service {
public List<MyConcreteClass> list(String location, MyEnums.mediaType type ) {
List<MyConcreteClass> list = null;
list.add(new MyConcreteClass(1, "foo", new byte[0]));
return list;
}
}
class MyConcreteClass implements Comparable<MyConcreteClass> {
private final long id;
private final String name;
private final byte[] data;
public MyConcreteClass(long id, String name, byte[] data) {
this.id = id;
this.name = name;
this.data = data;
}
#Override
public int compareTo(MyConcreteClass o) {
return this.name.compareTo(o.name);
}
// Other methods omitted for brevity
}
The above code is only a simplified example of the actual app code - which compiles and runs without any (known) runtime bugs. However I get the compiler warning:
Unchecked overriding: return type requires unchecked conversion.
The presence of a warning makes sense to me - code consuming the Service interface/API could break at runtime if the return type requirement in the calling code is incompatible with the implementation, whereas the error would be caught at compile if I had a more specific List<> defined in the interface.
This would, of course, not be an issue if I had to wire in a concrete implementation into the code consuming my service - however the joys of Spring!
What am I doing wrong? How can I fix this? Are generics the right way to achieve a polymorphic list() function in my case?
You can eliminate the unchecked cast by declaring the interface itself with a type parameter (instead of the method). Like this:
interface Service<T> {
List<T> list(String location, String type );
}
class LocalService implements Service<MyConcreteClass> {
#Override
public List<MyConcreteClass> list(String location, String type ) {
// Some logic to retrieve, alter and return a list
return null;
}
}
class StringService implements Service<String> {
#Override
public List<String> list(String location, String type) {
// TODO Auto-generated method stub
return null;
}
}
class MyConcreteClass {
/// ...
}
(I changed a couple of things to make it compile, not relevant to the answer).

Subclassing a ParseObject Subclass (Android)

Is it possible to subclass subclasses of ParseObjects? I am following the directions here. My class looks like this:
#ParseClassName("Stove")
public class Stove extends ParseObject{
private String URL = "url";
private String BRAND_NAME = "brand name";
public Stove() {
//Needed for Parse
}
public Stove(String url, String brandName) {
put(URL, url);
put(BRAND_NAME, brandName);
}
public String getUrl() {
return getString(URL);
}
public String getBrandName() {
return getString(BRAND_NAME);
}
...
}
and I have a subclass of this that looks like
#ParseClassName("ElectricStove")
public class ElectricStove extends Stove{
public ElectricStove() {
}
public ElectricStove(String url, String brandName) {
super(url, brandName);
}
...
}
My Application subclass is registered in AndroidManifest.xml and has this code in onCreate():
ParseObject.registerSubclass(Stove.class);
ParseObject.registerSubclass(ElectricStove.class);
...
Parse.initialize(this, "<lots of letters>", "<more letters>");
ParseInstallation.getCurrentInstallation().saveInBackground();
I'm getting this exception
Caused by: java.lang.IllegalArgumentException: You must register this ParseObject subclass before instantiating it.
at com.parse.ParseObject.<init>(ParseObject.java:363)
at com.parse.ParseObject.<init>(ParseObject.java:324)
at <package>.Stove.<init>(Stove.java:16)
at <package>.ElectricStove.<init>(ElectricStove.java:7)
which makes me wonder if I'm going about this in the wrong way or if it's perhaps simply not possible.
It's just not possible at this point, as Parse Android SDK does not support this. Rather, as a suggestion, use an identifier to specify what type of "Stove" a particular stove object is. Take this example:
#ParseClassName("Instrument")
public class Instrument extends ParseObject {
public Instrument() {
// A default constructor is required.
}
public InstrumentType getType() {
return InstrumentType.parse(getString("type"));
}
public void setType(InstrumentType type) {
put("type", type.toString());
}
then use:
final Instrument ocarina = new Instrument();
// Since our Instruments are strongly-typed, we can provide mutators that only take
// specific types, such as Strings, ParseUsers, or enum types.
ocarina.setType(InstrumentType.WOODWIND);
This would be a work-around of sorts to allow you to perform actions on an object based on it's type. It's not perfect, but it may suit your needs. The InstrumentType is just a class used for static constants in order to access id values
Example taken from here

How to get Child class?

I want to create an object of child class
more than 100 class extend MasterClass
MasterClass is
public class MasterClass{
int key;
String value;
String displayValue;
boolean status;
}
public class User extends MasterClass{
public User(){ }
}
public class Customer extends MasterClass{
String productName;
public Customer (){ }
}
etc...
i will get a MasterClass object from client, i wanted to type cast that object to respective one
if(masterClass instanceof User) {
User a_user = (User) a_ masterClass;
…
} else if(masterClass instanceof Customer) {
Customer a_customer = (Customer) a_ masterClass;
…
}
if i do this i will end up with 100s of else if.
Please let me know how i can achieve this without else if?
Thanks in advance.
Use polymorphism and generics, as Java intended.
Polymorphism lets you call a method on your object that behaves differently for every type. The easiest way to achieve this is to provide an abstract method in the base class MasterClass and then override it with different functionality in every extended class. You are probably looking for something like this:
class MasterClass {
int age;
// ...
public abstract void doWork();
public int getAge() { return age; }
// .. more methods
}
class User extends MasterClass {
// customize User here
#Override
public void doWork() { /* User does work in some way */ }
}
class Customer extends MasterClass {
// customize Customer here
#Override
public void doWork() { /* Customer does work in some other way */ }
}
// ...
If you are not too familiar with OOP, here is a good introductory tutorial.
If you are not allowed to alter your classes, you can populate a look-up table like HashMap<Class, MyFunctor> where you can assign a different functor for every type of person you have.
Also, you might want to use generics. Generics allow you to capture and restrict the type of objects passed to your methods.
Maybe you can use generics with the constraint T extends MasterClass?
Using basic concepts of Design Pattern you can create a constructor like this in the object where you try to initialize
MasterClass masterClass;
public MyCreatorOject(MasterClass masterClass)
{
this.masterClass = masterClass;
}
later when you create the object it can be
new MyCreatorObject(new User());
or
new MyCreatorObject(new Customer());

Extending enum fields Java

I know that it isn't possible to extend enum in Java, but I am trying to find an elegant solution for the below
I am trying to model enums (or classes) which will contain http end points of various web services across regions, say I have service A and B, each will have 4 region specific end points in US, EU, JP or CN. (This is basically for some seperate debug code that I am writing, in production the end points will be picked from configuration)
I was hoping to do something like this (not compliant java code).
public enum IEndPoint {
NA_END_POINT,
EU_END_POINT,
JP_END_POINT,
CN_END_POINT,
}
public enum ServiceAEndPoint extends IEndPoint {
NA_END_POINT("http://A.com/");
EU_END_POINT("http://A-eu.com/");
JP_END_POINT("http://A-jp.com/");
CN_END_POINT("http://A-cn.com/");
}
I could do this using interfaces where I have a method for each region, but in my opinion the enum way is more expressive, is there any better way I could model this ? What I am looking for is if there is any better way to model the inheritence relation and also having the expressive power of enumerations.
ServiceAEndPoint.NA_END_POINT
vs
serviceAEndPoint.getNAEndPoint()
I'm assuming that you will also want a ServiceBEndPoint enum (and similar). In which case I don't think your model really makes that much sense.
IEndPoint is really an enumeration of the kind of environments/regions where a service might be running. It is not an enumeration of the services themselves. Each individual service (A, B or whatever) will have different addresses for each of the regions.
Therefore I would stick with just the IEndPoint enum, and then in some service-specific code have a lookup map that will give you the address for a given end-point. Something like this:
public enum IEndPoint {
NA_END_POINT,
EU_END_POINT,
JP_END_POINT,
CN_END_POINT,
}
public class ServiceABroker {
private static final Map<IEndPoint, String> addressesByEndPoint;
static {
addressesByEndPoint = new EnumMap<>();
addressesByEndPoint.put(NA_END_POINT, "http://A.com/");
addressesByEndPoint.put(EU_END_POINT, "http://A-eu.com/");
addressesByEndPoint.put(JP_END_POINT, "http://A-jp.com/");
addressesByEndPoint.put(CN_END_POINT, "http://A-cn.com/");
}
public String getAddressForEndPoint(IEndPoint ep) {
return addressesByEndPoint.get(ep);
}
}
If these are static final constants, then just put them in an interface. Name the interface something like IServiceAEndPointKeys, where the keys part is a convention.
Here's where I consider enums to be more appropriate and useful:
Example 1: File type. An enum containing jpg, pdf etc.
Example 2: Column definitions. If I have a table with 3 columns, I would write an enum declaring ID, Name, Description (for example), each one having parameters like column header name, column width and column ID.
Im not sure I understand you question, but you can add methods to an enum for example you could do something like the following:
public enum ServiceAEndPoint{
NA_END_POINT("http://A.com/");
EU_END_POINT("http://A-eu.com/");
JP_END_POINT("http://A-jp.com/");
CN_END_POINT("http://A-cn.com/");
private final String url;
private EndPoint(String url){
this.url=url;
}
public String getURL(){
return url;
}
}
Enums cannot be extended in such a manner, mostly because enums cannot be sub-classed or the constraints they must adhere to will not be possible to impose.
Instead leverage interfaces, like so
public interface IEndPoint;
public enum DefaultEndPoints implements IEndPoint {
NA_END_POINT,
EU_END_POINT,
JP_END_POINT,
CN_END_POINT,
}
public enum DefaultServiceEndPoints implements IEndPoint {
NA_END_POINT("http://A.com/");
EU_END_POINT("http://A-eu.com/");
JP_END_POINT("http://A-jp.com/");
CN_END_POINT("http://A-cn.com/");
}
public void doSomething(IEndPoint endpoint) {
...
}
The reason why one can't subclass in the manner you wish is related to the contract that enums will be both equal via .equals(object) and via ==. If you could subclass, would this make sense?
if ( (DefaultEndPoints)JP_END_POINT == (DefaultServiceEndPoints)JP_END_POINT) {
}
if you say "yes" then I would expect to be able to do this
DefaultEndPoint someEndpoint = DefaultServiceEndPoints.JP_END_POINT;
which would leave a door open for error, as there is no guarantee that a enum entry in one enum declaration is in the other enum declaration.
Could it be different? Perhaps, but it isn't, and changing it would definately introduce a lot of complications that would have to be thoroughly thought out (or it would open avenues to work around Java's strong static-type checking).
You may want to consider something like this:
public abstract class EndpointFactory {
public abstract String getNAEndPoint();
public abstract String getEUEndPoint();
}
public class ServiceAEndpointFactory extends EndpointFactory {
public static final String NA_END_POINT = "http://A.com/";
public static final String EU_END_POINT = "http://A-eu.com/";
public String getNAEndPoint() {
return ServiceAEndpointFactory.NA_END_POINT;
}
public String getEUEndPoint() {
return ServiceAEndpointFactory.EU_END_POINT;
}
}
public class ServiceBEndpointFactory extends EndpointFactory {
public static final String NA_END_POINT = "http://B.com/";
public static final String EU_END_POINT = "http://B-eu.com/";
public String getNAEndPoint() {
return ServiceAEndpointFactory.NA_END_POINT;
}
public String getEUEndPoint() {
return ServiceAEndpointFactory.EU_END_POINT;
}
}
Then you can refer to your strings directly like this:
ServiceAEndpointFactory.NA_END_POINT;
Or, you can use the base object if the type of service is not known until execution:
EndpointFactory ef1 = new ServiceAEndpointFactory();
String ep = ef1.getNAEndPoint();
The drawback of this is the redefinition of the get*Endpoint() functions in each sub-class. You could eliminate that by moving the static final variables to be not static in the base class and putting the getter/setter in the base class only one time. However, the drawback of that is you are not able to reference the values without instantiating an object (which essentially emulates what I find valuable with ENUMs).
How does a pattern like this appeal to you? I let the enum implement an interface and implement the interface in a Debug set and a Release set. The release set can then derive the property name from the enum name - which is neat.
public interface HasURL {
public String getURL();
}
public enum DebugEndPoints implements HasURL {
NA,
EU,
JP,
CN;
#Override
public String getURL() {
// Force debug to go to the same one always.
return "http://Debug.com/";
}
}
public enum NormalEndPoints implements HasURL {
NA,
EU,
JP,
CN;
final String url;
NormalEndPoints () {
// Grab the configured property connected to my name.
this.url = getProperty(this.name());
}
#Override
public String getURL() {
return url;
}
}

Design patterns for converting objects with nested lists

I have a service where the flow is basically the following:
Receive an input object. This is just a POJO object and I don't have much say in the design of it.
Convert to a normalized object for my service.
Perform some business logic on the normalized object, and gather some extra data about it.
Convert to an output object for another service that the data gets passed to. (Another POJO.)
Pass the converted data to another service.
What this means, though, is that a good portion of my service is converting from type InputFoo to type NormalizedFoo to type OutputFoo.
This would be a pretty easy task. I'm using the Google Collections library and can have a class like this:
public class InputFooToNormalizedFooConverter implements Function<InputFoo, NormalizedFoo> {
public NormalizedFoo apply(InputFoo input) {
NormalizedFoo output = new NormalizedFoo();
output.setProperty(input.getProperty());
}
}
and another class like this:
public class NormalizedFooFooToOutputFooConverter implements Function<NormalizedFoo, OutputFoo> {
public NormalizedFoo apply(InputFoo input) {
NormalizedFoo output = new NormalizedFoo();
output.setProperty(input.getProperty());
}
}
But each type of Foo essentially has a hierarchy like so:
public class Foo {
List<Bar> barItems;
// .. other properties
}
public class Bar {
List<Baz> bazItems;
List<Quux> quuxItems;
// .. other properties
}
public class Baz {
// .. other properties
}
public class Quux {
// .. other properties
}
This means that I have NormalizedFooToOutputFooConverter that has a NormalizedBarToOutputBarConverter implements Function<NormalizedBar, OutputBar> type and so on and so forth.
Even worse, the input doesn't quite match up exactly to the normalized model. It's more like
public class InputFoo {
public List<InputBar> bars;
public List<InputBaz> bazs;
public List<InputQuux> quuxs;
// .. other properties
}
public class InputBar {
private String barId;
// .. other properties
}
public class InputBaz {
private String barId;
private String bazId;
// .. other properties
}
public class InputQuux {
private String barId;
private String quuxId;
// .. other properties
}
In these models, I can figure out which Baz and Quux belongs to which Bar based on the barId that each one has.
At this point, I have about 20 different converters for going from Input to Normalized and Normalized to Output. And worse still, some of them have name like ReallyLongInputTypeToReallyLongNormalizedTypeConverter creating extremely long class names. I feel like I'm doing something wrong here, with all the converters. Is there a better way to organize my converters?

Categories

Resources