-1

I have an API that processes a set of objects all extending a particular class which does not have an income field

class Person { ... }

Say I want to make a call getting incomes. Not all of the subclasses here have an income field

class Child { ... }
class FullTimeEmployedPerson { ... }
class TrustFundKid { ... }

This process would call a #getIncome() method on either of the latter two. Now, my API is guaranteed never to get a Child passed to it so I want to skip the pleasantries and simply have something like

String getParsedIncome(Person person) { 
    return FooBar.parse(person.getIncome());
}

What is a realistic approach for this?

Layman
  • 597
  • 3
  • 16
  • Can you change the classes or not? It sounds like you can but it also sounds like it's from a 3rd party library (so you can't change them). Please [edit] your question to include all classes extending from `Person`. – Progman Jan 03 '20 at 00:42
  • 2
    What kind of API are you talking about? (I take it you mean REST + json) You can define an interface with a [default method](https://docs.oracle.com/javase/tutorial/java/IandI/defaultmethods.html) `Optional getIncome()`. Your classes are all implementing the interface, but only `FullTimeEmployedPerson`and `TrustFundKid` are actually returning non-empty objects. – SME_Dev Jan 03 '20 at 00:42
  • Person class is a hypothetical example here, I cannot realistically include all subclasses from some decades old legacy application and it would not help the question more. I do not get to touch the classes involved, my API maps them to different objects depending on specs (which change way too often) – Layman Jan 03 '20 at 00:45
  • @VictorS But the mapped classes are under your control? So you can add/change classes and interfaces as you like? – Progman Jan 03 '20 at 00:50
  • Nope. Unless I create a facade class that would map to each end of the business logic separately – Layman Jan 03 '20 at 00:54
  • 1
    For [duck typing](https://en.wikipedia.org/wiki/Duck_typing) Java [isn't ideal](https://stackoverflow.com/questions/1079785/whats-an-example-of-duck-typing-in-java). – SDJ Jan 03 '20 at 01:04
  • @VictorS It is a little bit unclear what you are asking for or what the problem is. Please [edit] your question to make it more clear what classes you get from the 3rd party library and how you want/plan to consume them in your application. Also explain how changes in the external API/classes will affect you. And describe how you will call a method like `getIncome()` when this method is not present in the base class you are using. This *might* sound like a "XY problem", but not quite yet... – Progman Jan 03 '20 at 01:13
  • @Progman I added the tidbit about it being useful in real life so that I would not get swarmed by suggestions to just implement everything completely differently. The oddly invasive details you are requesting are not relevant to the question and I am not going to include those details. If you'd prefer consider that last paragraph does not exist. – Layman Jan 03 '20 at 01:19
  • @VictorS Is it an option to use `getClass()` or `instanceof` to check if an object is a specific subclass object and cast the given object to that specific subclass object, where the method exist you want to call? – Progman Jan 03 '20 at 01:23
  • That is mainly what I want to avoid. My goal is to have the call agnostic to which specific subclass it is, except that it is a subclass of ```Person``` – Layman Jan 03 '20 at 01:26
  • 1
    @VictorS What about https://stackoverflow.com/questions/3935832/java-equivalent-to-c-sharp-dynamic-class-type? This simulates the `dynamic` keyword from C#. – Progman Jan 03 '20 at 01:32

2 Answers2

2

Define getIncome() in Person, throwing UnsupportedOperationException. Override this in subclasses where it is supported to return the income.

You say that it is guaranteed that only supported fields will be accessed. This approach abandons compile-time checks to ensure that is true. An alternative would be to create an interface, IncomeHolder, and implement it only in subclasses of Person that actually have an income. Then the compiler can guarantee there is no invalid usage.

erickson
  • 257,800
  • 54
  • 385
  • 479
0

You have to use reflection to check if your instance class has such method.

If(YourChildInstance.class.getMethod("methodName") != null){ ... }else{ do nothing}

I'm not 100% sure that it works. Test it and let me know if it does

Tito Tigi
  • 53
  • 1
  • 10
  • unfortunately reflections are not a solution with high TPS requirements due to how expensive they are. also they do not help with maintainability either – Layman Jan 03 '20 at 00:34