mercredi 28 février 2018

What's the best way to write adapters around inherited classes in java?

I have some Logic:

public interface Logic {
  Object doSomething(LogicData data);
}

The LogicData is supposed to hold data fields that different implementations of the Logic could use, given that not all Logics would need all data to be there:

public class FirstLogic implements Logic {
  Object doSomething(LogicData data) {
    // Uses data.x;
  }
}

public class SecondLogic implements Logic {
  Object doSomething(LogicData data) {
    // Uses data.y;
  }
}

I'm now trying to write a LogicData interface which I could later extend by writing adapters, and it goes like this:

public interface LogicData {
  X getX();
  Y getY();
}

Here comes the tricky part. I'm trying to write adapters that would extend this LogicData. The adapters are to take in a hierarchy that look like this:

public abstract class CommonData {
 X x;
}
public class SpecificData extends CommonData {
 Y y;
}
public class OtherData extends CommonData {
 ...
}

Thus, I've written a generic adapter that looks like this:

public abstract class CommonLogicDataAdapter<Data extends CommonData> implements LogicData {
  ActivityData data;

  @Override
  X getX() { return data.getX(); }
} 

Now I need a concrete adapter. This one can handle the SpecificData:

public abstract class SpecificLogicDataAdapter<Data extends SpecificData> extends  CommonLogicDataAdapter {
  ActivityData data;

  @Override
  Y getY() { return data.getY(); }
} 

All's good in the world, right? Nope. Now I'm stuck as to the best way I can write an adapter for OtherData. The problem with OtherData is that it can getX() but can't getY(), but that's fine. As I said, not all Logics need all Data. I still want to be able to use OtherData with FirstLogic, even though it can't be used with SecondLogic.

Here are my options:

  1. Throw an UnsupportedOperationException/return null in OtherData's getY(). This would mean relying on the developer to not make that mistake, but I'd rather get a compiler error instead. It would also mean though that using my adapters would require try-catch blocks/null checks, which I really don't want to do.
  2. Separate LogicData into LogicDataX and LogicDataY, but now I can't write decorators that would chain my Logic if I wanted to.
  3. Make LogicData getX only and extend it with another implementation LogicDataY which would getY, but that would entail changing SecondLogic to take a LogicDataY as a parameter and now I also can't chain my logic.

What's the best way to write adapters around inherited classes in java?

Aucun commentaire:

Enregistrer un commentaire