Passing an argument that could be of multiple types to a method in Java?












1














I am using a library with a method foo with a signature like this:



TypeR foo(TypeA first, int second)
TypeR foo(TypeB first, int second)
TypeR foo(TypeC first, int second)


I am writing my own method bar calling foo, and I want to directly pass the first parameter along to foo:



bar(??? first, int baz) {
int second = someCalculation(baz);
return foo(first, second);
}


My problem is that I do not know what type I should give to the parameter first in bar. There does not seem to be union typs in Java. How can I solve this without having to write three almost identical versions of bar?



The types TypeA to TypeC do not share a common interface, and I have no control over them or foo since they are in an external library. All I can control is how I implement bar.










share|improve this question
























  • if TypeA, TypeB, and TypeC all extend a common base class or implement a common interface, then write your method in terms of 'that' type. Otherwise, you may be able to use a 'Generic Type'
    – Tom Drake
    Nov 20 at 19:56
















1














I am using a library with a method foo with a signature like this:



TypeR foo(TypeA first, int second)
TypeR foo(TypeB first, int second)
TypeR foo(TypeC first, int second)


I am writing my own method bar calling foo, and I want to directly pass the first parameter along to foo:



bar(??? first, int baz) {
int second = someCalculation(baz);
return foo(first, second);
}


My problem is that I do not know what type I should give to the parameter first in bar. There does not seem to be union typs in Java. How can I solve this without having to write three almost identical versions of bar?



The types TypeA to TypeC do not share a common interface, and I have no control over them or foo since they are in an external library. All I can control is how I implement bar.










share|improve this question
























  • if TypeA, TypeB, and TypeC all extend a common base class or implement a common interface, then write your method in terms of 'that' type. Otherwise, you may be able to use a 'Generic Type'
    – Tom Drake
    Nov 20 at 19:56














1












1








1







I am using a library with a method foo with a signature like this:



TypeR foo(TypeA first, int second)
TypeR foo(TypeB first, int second)
TypeR foo(TypeC first, int second)


I am writing my own method bar calling foo, and I want to directly pass the first parameter along to foo:



bar(??? first, int baz) {
int second = someCalculation(baz);
return foo(first, second);
}


My problem is that I do not know what type I should give to the parameter first in bar. There does not seem to be union typs in Java. How can I solve this without having to write three almost identical versions of bar?



The types TypeA to TypeC do not share a common interface, and I have no control over them or foo since they are in an external library. All I can control is how I implement bar.










share|improve this question















I am using a library with a method foo with a signature like this:



TypeR foo(TypeA first, int second)
TypeR foo(TypeB first, int second)
TypeR foo(TypeC first, int second)


I am writing my own method bar calling foo, and I want to directly pass the first parameter along to foo:



bar(??? first, int baz) {
int second = someCalculation(baz);
return foo(first, second);
}


My problem is that I do not know what type I should give to the parameter first in bar. There does not seem to be union typs in Java. How can I solve this without having to write three almost identical versions of bar?



The types TypeA to TypeC do not share a common interface, and I have no control over them or foo since they are in an external library. All I can control is how I implement bar.







java methods types






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited Nov 20 at 20:08

























asked Nov 20 at 19:49









Anders

5,50463052




5,50463052












  • if TypeA, TypeB, and TypeC all extend a common base class or implement a common interface, then write your method in terms of 'that' type. Otherwise, you may be able to use a 'Generic Type'
    – Tom Drake
    Nov 20 at 19:56


















  • if TypeA, TypeB, and TypeC all extend a common base class or implement a common interface, then write your method in terms of 'that' type. Otherwise, you may be able to use a 'Generic Type'
    – Tom Drake
    Nov 20 at 19:56
















if TypeA, TypeB, and TypeC all extend a common base class or implement a common interface, then write your method in terms of 'that' type. Otherwise, you may be able to use a 'Generic Type'
– Tom Drake
Nov 20 at 19:56




if TypeA, TypeB, and TypeC all extend a common base class or implement a common interface, then write your method in terms of 'that' type. Otherwise, you may be able to use a 'Generic Type'
– Tom Drake
Nov 20 at 19:56












6 Answers
6






active

oldest

votes


















4














The closest I can think of is something like this (removing the stuff relating to second since it is irrelevant to the point).



TypeR bar(Object first) {
TypeR retvalue;
if (first instanceof TypeA)
retvalue = foo( (TypeA)first );
else if (first instanceof TypeB)
retvalue = foo( (TypeB)first );
else if (first instanceof TypeC)
retvalue = foo( (TypeC)first );
return retvalue;
}


If there is a more specific known supertype of TypeA etc., you could obviously use that instead of Object as the parameter.



This is only possible if all three versions of foo have the same return type.



Sadly, this "solution" is not really better, and maybe worse, than writing three overloaded versions of bar.






share|improve this answer























  • it is not a good practice to use instaceof
    – elbraulio
    Nov 20 at 20:03










  • I'm not particularly interested in blanket statements of what is "good practice". If you really think so, perhaps you could explain why. In any case, I simply posted the only technique I can think of that approaches what the poster is requesting.
    – Dave Costa
    Nov 20 at 20:08










  • @SotiriosDelimanolis maybe I'm misunderstanding your comment, but I think I possibly didn't explain. Since the OP didn't specify the return type of the functions, I just used T as a placeholder in my sample code. In reality I would replace it with int or whatever is the appropriate return type. I didn't mean to imply that the compiler would figure out the return type on its own.
    – Dave Costa
    Nov 20 at 20:09












  • +1 for both pointing to a solution, and highlighting that overloading might be better. I updated the question to clarify that all versions of foo share the same return type.
    – Anders
    Nov 20 at 20:09










  • @BraulioLopez I would be interested in references for why it's bad practice to use instanceof. In the case of working with 3rd party APIs in which you have no control over the class hierarchy, and which were possibly written prior to the advent of generics in Java, using instanceof seems perfectly reasonable.
    – Mike
    Nov 20 at 20:15



















3














In theory, nothing prevents you from using typeclasses for ad-hoc polymorphism in Java:



interface Fooable<T> {
int foo(T t, int second);
}

public int bar<T>(T t, int baz, Fooable<T> fooable) {
int second = someCalculation(baz);
return fooable.foo(t, second);
}


The implementations would look roughly as follows:



public class TypeAFooable implements Fooable<TypeA> {
public int foo(TypeA t, int second) { return yourLibrary.foo(t, second); }
}


And invocations would look like



bar(myTypeAThing, 1234, new TypeAFooable());


If bar were a little bit longer, this would bring several advantages:




  • if bar makes lots of calls to foo in lots of different places, then you could define each instance of the typeclass once, instead of having multiple if-instanceof-branches inside of bar

  • if you later want to make it work with TypeD, TypeE, ..., TypeZ, you don't have to dig into code of bar, you can simply supply yet another typeclass implementation

  • more importantly: if someone else wanted to use it with TypeD, TypeE, etc., then they could supply yet another typeclass implementation, without having to fork your bar implementation.


In practice, the problem is that the typeclass instances won't be supplied automatically by the compiler, so it's usually not worth the hassle. Unless bar is somehow gigantic and super-complex, just overload it, or use instanceof.






share|improve this answer































    1














    You can define first as a generic type type in bar as below.



    bar(Object first, int baz) {
    int second = someCalculation(baz);
    if(first instanceOf TypeA) return foo((TypeA) first, second);
    else if(first instanceOf TypeB) return foo((TypeB) first, second);
    else if(first instanceOf TypeC) return foo((TypeC) first, second);
    else throw new CustomException("Object pass in is not of correct type");
    }





    share|improve this answer































      1














      I would attempt to avoid this problem by decomposing your bar() function into the piece that deals with computing int second and the piece that deals with TypeA/B/C first. That way you could write something like



      int second = decomposedPortion(baz);
      TypeR result = foo(first, second);





      share|improve this answer





























        1














        We can replace the call of foo in bar by a call of a corresponding BiFunction. Thus for all overloaded foo methods a BiFunction has to be defined.



          private static final Map<Class<?>, BiFunction<?, Integer, TypeR>> FOO = Map.of(
        TypeA.class, (first, second) -> foo((TypeA) first, second),
        TypeB.class, (first, second) -> foo((TypeB) first, second),
        TypeC.class, (first, second) -> foo((TypeC) first, second));


        But for every overloaded foo mapping one line only has to be written whereas each overloaded bar method would need four lines if it were written as like in the question.



        Now we can make bar generic. But the following will not work, since the returned BiFunction has an unbound wildcard as first type parameter.



          <T> TypeR bar(T first, int baz) {
        int second = someCalculation(baz);
        return FOO.get(first.getClass()).apply(first, second);
        }


        We would need to declare FOO as Map<Class<T>, BiFunction<T, Integer, TypeR>> but that's not possible. To work around this we define a method with a type parameter T which is supposed to establish the missing type equality. But that's not for free. It's at the cost of a warning resulting from casting:



          private static <T> BiFunction<T, Integer, TypeR> fooOf(Object o) {
        return (BiFunction<T, Integer, TypeR>) FOO.get(o.getClass());
        }


        Now we can use this method in bar:



          <T> TypeR bar(T first, int baz) {
        int second = someCalculation(baz);
        return fooOf(first).apply(first, second);
        }


        This is similar to an instanceof approach but displaces the type distinction from the method bar to the Map FOO. If there are other methods than bar which also need to call foo in a similar way, the type distinction has not be coded again. FOO and fooOf can be reused. If the library changes and an additional overloaded TypeR foo(TypeD first, int second) gets introduced, only FOO needs to be updated by adding one additional line.



        This approach requires first to be not null.






        share|improve this answer































          -1














          Use interfaces like this:



          interface Type { //...}

          class TypeA implements Type { //...}

          class TypeB implements Type { //...}

          class TypeC implements Type { //...}


          then you will only need one foo function



          foo(Type first, int second)



          and one bar function



          bar(Type first, int baz)






          share|improve this answer

















          • 1




            Yes, this would be a good design approach if the poster had the option. Unfortunately, the question states that the foo() methods are in a library.
            – Dave Costa
            Nov 20 at 19:57










          • They do not implement a common interface, and I have no controls over typeA to typeC or foo.
            – Anders
            Nov 20 at 19:57










          • how do you decide wich type must be used to call foo?
            – elbraulio
            Nov 20 at 20:00












          • I don't understand your question?
            – Anders
            Nov 20 at 20:07











          Your Answer






          StackExchange.ifUsing("editor", function () {
          StackExchange.using("externalEditor", function () {
          StackExchange.using("snippets", function () {
          StackExchange.snippets.init();
          });
          });
          }, "code-snippets");

          StackExchange.ready(function() {
          var channelOptions = {
          tags: "".split(" "),
          id: "1"
          };
          initTagRenderer("".split(" "), "".split(" "), channelOptions);

          StackExchange.using("externalEditor", function() {
          // Have to fire editor after snippets, if snippets enabled
          if (StackExchange.settings.snippets.snippetsEnabled) {
          StackExchange.using("snippets", function() {
          createEditor();
          });
          }
          else {
          createEditor();
          }
          });

          function createEditor() {
          StackExchange.prepareEditor({
          heartbeatType: 'answer',
          autoActivateHeartbeat: false,
          convertImagesToLinks: true,
          noModals: true,
          showLowRepImageUploadWarning: true,
          reputationToPostImages: 10,
          bindNavPrevention: true,
          postfix: "",
          imageUploader: {
          brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
          contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
          allowUrls: true
          },
          onDemand: true,
          discardSelector: ".discard-answer"
          ,immediatelyShowMarkdownHelp:true
          });


          }
          });














          draft saved

          draft discarded


















          StackExchange.ready(
          function () {
          StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53400523%2fpassing-an-argument-that-could-be-of-multiple-types-to-a-method-in-java%23new-answer', 'question_page');
          }
          );

          Post as a guest















          Required, but never shown

























          6 Answers
          6






          active

          oldest

          votes








          6 Answers
          6






          active

          oldest

          votes









          active

          oldest

          votes






          active

          oldest

          votes









          4














          The closest I can think of is something like this (removing the stuff relating to second since it is irrelevant to the point).



          TypeR bar(Object first) {
          TypeR retvalue;
          if (first instanceof TypeA)
          retvalue = foo( (TypeA)first );
          else if (first instanceof TypeB)
          retvalue = foo( (TypeB)first );
          else if (first instanceof TypeC)
          retvalue = foo( (TypeC)first );
          return retvalue;
          }


          If there is a more specific known supertype of TypeA etc., you could obviously use that instead of Object as the parameter.



          This is only possible if all three versions of foo have the same return type.



          Sadly, this "solution" is not really better, and maybe worse, than writing three overloaded versions of bar.






          share|improve this answer























          • it is not a good practice to use instaceof
            – elbraulio
            Nov 20 at 20:03










          • I'm not particularly interested in blanket statements of what is "good practice". If you really think so, perhaps you could explain why. In any case, I simply posted the only technique I can think of that approaches what the poster is requesting.
            – Dave Costa
            Nov 20 at 20:08










          • @SotiriosDelimanolis maybe I'm misunderstanding your comment, but I think I possibly didn't explain. Since the OP didn't specify the return type of the functions, I just used T as a placeholder in my sample code. In reality I would replace it with int or whatever is the appropriate return type. I didn't mean to imply that the compiler would figure out the return type on its own.
            – Dave Costa
            Nov 20 at 20:09












          • +1 for both pointing to a solution, and highlighting that overloading might be better. I updated the question to clarify that all versions of foo share the same return type.
            – Anders
            Nov 20 at 20:09










          • @BraulioLopez I would be interested in references for why it's bad practice to use instanceof. In the case of working with 3rd party APIs in which you have no control over the class hierarchy, and which were possibly written prior to the advent of generics in Java, using instanceof seems perfectly reasonable.
            – Mike
            Nov 20 at 20:15
















          4














          The closest I can think of is something like this (removing the stuff relating to second since it is irrelevant to the point).



          TypeR bar(Object first) {
          TypeR retvalue;
          if (first instanceof TypeA)
          retvalue = foo( (TypeA)first );
          else if (first instanceof TypeB)
          retvalue = foo( (TypeB)first );
          else if (first instanceof TypeC)
          retvalue = foo( (TypeC)first );
          return retvalue;
          }


          If there is a more specific known supertype of TypeA etc., you could obviously use that instead of Object as the parameter.



          This is only possible if all three versions of foo have the same return type.



          Sadly, this "solution" is not really better, and maybe worse, than writing three overloaded versions of bar.






          share|improve this answer























          • it is not a good practice to use instaceof
            – elbraulio
            Nov 20 at 20:03










          • I'm not particularly interested in blanket statements of what is "good practice". If you really think so, perhaps you could explain why. In any case, I simply posted the only technique I can think of that approaches what the poster is requesting.
            – Dave Costa
            Nov 20 at 20:08










          • @SotiriosDelimanolis maybe I'm misunderstanding your comment, but I think I possibly didn't explain. Since the OP didn't specify the return type of the functions, I just used T as a placeholder in my sample code. In reality I would replace it with int or whatever is the appropriate return type. I didn't mean to imply that the compiler would figure out the return type on its own.
            – Dave Costa
            Nov 20 at 20:09












          • +1 for both pointing to a solution, and highlighting that overloading might be better. I updated the question to clarify that all versions of foo share the same return type.
            – Anders
            Nov 20 at 20:09










          • @BraulioLopez I would be interested in references for why it's bad practice to use instanceof. In the case of working with 3rd party APIs in which you have no control over the class hierarchy, and which were possibly written prior to the advent of generics in Java, using instanceof seems perfectly reasonable.
            – Mike
            Nov 20 at 20:15














          4












          4








          4






          The closest I can think of is something like this (removing the stuff relating to second since it is irrelevant to the point).



          TypeR bar(Object first) {
          TypeR retvalue;
          if (first instanceof TypeA)
          retvalue = foo( (TypeA)first );
          else if (first instanceof TypeB)
          retvalue = foo( (TypeB)first );
          else if (first instanceof TypeC)
          retvalue = foo( (TypeC)first );
          return retvalue;
          }


          If there is a more specific known supertype of TypeA etc., you could obviously use that instead of Object as the parameter.



          This is only possible if all three versions of foo have the same return type.



          Sadly, this "solution" is not really better, and maybe worse, than writing three overloaded versions of bar.






          share|improve this answer














          The closest I can think of is something like this (removing the stuff relating to second since it is irrelevant to the point).



          TypeR bar(Object first) {
          TypeR retvalue;
          if (first instanceof TypeA)
          retvalue = foo( (TypeA)first );
          else if (first instanceof TypeB)
          retvalue = foo( (TypeB)first );
          else if (first instanceof TypeC)
          retvalue = foo( (TypeC)first );
          return retvalue;
          }


          If there is a more specific known supertype of TypeA etc., you could obviously use that instead of Object as the parameter.



          This is only possible if all three versions of foo have the same return type.



          Sadly, this "solution" is not really better, and maybe worse, than writing three overloaded versions of bar.







          share|improve this answer














          share|improve this answer



          share|improve this answer








          edited Nov 20 at 20:11









          Anders

          5,50463052




          5,50463052










          answered Nov 20 at 20:02









          Dave Costa

          38.6k54664




          38.6k54664












          • it is not a good practice to use instaceof
            – elbraulio
            Nov 20 at 20:03










          • I'm not particularly interested in blanket statements of what is "good practice". If you really think so, perhaps you could explain why. In any case, I simply posted the only technique I can think of that approaches what the poster is requesting.
            – Dave Costa
            Nov 20 at 20:08










          • @SotiriosDelimanolis maybe I'm misunderstanding your comment, but I think I possibly didn't explain. Since the OP didn't specify the return type of the functions, I just used T as a placeholder in my sample code. In reality I would replace it with int or whatever is the appropriate return type. I didn't mean to imply that the compiler would figure out the return type on its own.
            – Dave Costa
            Nov 20 at 20:09












          • +1 for both pointing to a solution, and highlighting that overloading might be better. I updated the question to clarify that all versions of foo share the same return type.
            – Anders
            Nov 20 at 20:09










          • @BraulioLopez I would be interested in references for why it's bad practice to use instanceof. In the case of working with 3rd party APIs in which you have no control over the class hierarchy, and which were possibly written prior to the advent of generics in Java, using instanceof seems perfectly reasonable.
            – Mike
            Nov 20 at 20:15


















          • it is not a good practice to use instaceof
            – elbraulio
            Nov 20 at 20:03










          • I'm not particularly interested in blanket statements of what is "good practice". If you really think so, perhaps you could explain why. In any case, I simply posted the only technique I can think of that approaches what the poster is requesting.
            – Dave Costa
            Nov 20 at 20:08










          • @SotiriosDelimanolis maybe I'm misunderstanding your comment, but I think I possibly didn't explain. Since the OP didn't specify the return type of the functions, I just used T as a placeholder in my sample code. In reality I would replace it with int or whatever is the appropriate return type. I didn't mean to imply that the compiler would figure out the return type on its own.
            – Dave Costa
            Nov 20 at 20:09












          • +1 for both pointing to a solution, and highlighting that overloading might be better. I updated the question to clarify that all versions of foo share the same return type.
            – Anders
            Nov 20 at 20:09










          • @BraulioLopez I would be interested in references for why it's bad practice to use instanceof. In the case of working with 3rd party APIs in which you have no control over the class hierarchy, and which were possibly written prior to the advent of generics in Java, using instanceof seems perfectly reasonable.
            – Mike
            Nov 20 at 20:15
















          it is not a good practice to use instaceof
          – elbraulio
          Nov 20 at 20:03




          it is not a good practice to use instaceof
          – elbraulio
          Nov 20 at 20:03












          I'm not particularly interested in blanket statements of what is "good practice". If you really think so, perhaps you could explain why. In any case, I simply posted the only technique I can think of that approaches what the poster is requesting.
          – Dave Costa
          Nov 20 at 20:08




          I'm not particularly interested in blanket statements of what is "good practice". If you really think so, perhaps you could explain why. In any case, I simply posted the only technique I can think of that approaches what the poster is requesting.
          – Dave Costa
          Nov 20 at 20:08












          @SotiriosDelimanolis maybe I'm misunderstanding your comment, but I think I possibly didn't explain. Since the OP didn't specify the return type of the functions, I just used T as a placeholder in my sample code. In reality I would replace it with int or whatever is the appropriate return type. I didn't mean to imply that the compiler would figure out the return type on its own.
          – Dave Costa
          Nov 20 at 20:09






          @SotiriosDelimanolis maybe I'm misunderstanding your comment, but I think I possibly didn't explain. Since the OP didn't specify the return type of the functions, I just used T as a placeholder in my sample code. In reality I would replace it with int or whatever is the appropriate return type. I didn't mean to imply that the compiler would figure out the return type on its own.
          – Dave Costa
          Nov 20 at 20:09














          +1 for both pointing to a solution, and highlighting that overloading might be better. I updated the question to clarify that all versions of foo share the same return type.
          – Anders
          Nov 20 at 20:09




          +1 for both pointing to a solution, and highlighting that overloading might be better. I updated the question to clarify that all versions of foo share the same return type.
          – Anders
          Nov 20 at 20:09












          @BraulioLopez I would be interested in references for why it's bad practice to use instanceof. In the case of working with 3rd party APIs in which you have no control over the class hierarchy, and which were possibly written prior to the advent of generics in Java, using instanceof seems perfectly reasonable.
          – Mike
          Nov 20 at 20:15




          @BraulioLopez I would be interested in references for why it's bad practice to use instanceof. In the case of working with 3rd party APIs in which you have no control over the class hierarchy, and which were possibly written prior to the advent of generics in Java, using instanceof seems perfectly reasonable.
          – Mike
          Nov 20 at 20:15













          3














          In theory, nothing prevents you from using typeclasses for ad-hoc polymorphism in Java:



          interface Fooable<T> {
          int foo(T t, int second);
          }

          public int bar<T>(T t, int baz, Fooable<T> fooable) {
          int second = someCalculation(baz);
          return fooable.foo(t, second);
          }


          The implementations would look roughly as follows:



          public class TypeAFooable implements Fooable<TypeA> {
          public int foo(TypeA t, int second) { return yourLibrary.foo(t, second); }
          }


          And invocations would look like



          bar(myTypeAThing, 1234, new TypeAFooable());


          If bar were a little bit longer, this would bring several advantages:




          • if bar makes lots of calls to foo in lots of different places, then you could define each instance of the typeclass once, instead of having multiple if-instanceof-branches inside of bar

          • if you later want to make it work with TypeD, TypeE, ..., TypeZ, you don't have to dig into code of bar, you can simply supply yet another typeclass implementation

          • more importantly: if someone else wanted to use it with TypeD, TypeE, etc., then they could supply yet another typeclass implementation, without having to fork your bar implementation.


          In practice, the problem is that the typeclass instances won't be supplied automatically by the compiler, so it's usually not worth the hassle. Unless bar is somehow gigantic and super-complex, just overload it, or use instanceof.






          share|improve this answer




























            3














            In theory, nothing prevents you from using typeclasses for ad-hoc polymorphism in Java:



            interface Fooable<T> {
            int foo(T t, int second);
            }

            public int bar<T>(T t, int baz, Fooable<T> fooable) {
            int second = someCalculation(baz);
            return fooable.foo(t, second);
            }


            The implementations would look roughly as follows:



            public class TypeAFooable implements Fooable<TypeA> {
            public int foo(TypeA t, int second) { return yourLibrary.foo(t, second); }
            }


            And invocations would look like



            bar(myTypeAThing, 1234, new TypeAFooable());


            If bar were a little bit longer, this would bring several advantages:




            • if bar makes lots of calls to foo in lots of different places, then you could define each instance of the typeclass once, instead of having multiple if-instanceof-branches inside of bar

            • if you later want to make it work with TypeD, TypeE, ..., TypeZ, you don't have to dig into code of bar, you can simply supply yet another typeclass implementation

            • more importantly: if someone else wanted to use it with TypeD, TypeE, etc., then they could supply yet another typeclass implementation, without having to fork your bar implementation.


            In practice, the problem is that the typeclass instances won't be supplied automatically by the compiler, so it's usually not worth the hassle. Unless bar is somehow gigantic and super-complex, just overload it, or use instanceof.






            share|improve this answer


























              3












              3








              3






              In theory, nothing prevents you from using typeclasses for ad-hoc polymorphism in Java:



              interface Fooable<T> {
              int foo(T t, int second);
              }

              public int bar<T>(T t, int baz, Fooable<T> fooable) {
              int second = someCalculation(baz);
              return fooable.foo(t, second);
              }


              The implementations would look roughly as follows:



              public class TypeAFooable implements Fooable<TypeA> {
              public int foo(TypeA t, int second) { return yourLibrary.foo(t, second); }
              }


              And invocations would look like



              bar(myTypeAThing, 1234, new TypeAFooable());


              If bar were a little bit longer, this would bring several advantages:




              • if bar makes lots of calls to foo in lots of different places, then you could define each instance of the typeclass once, instead of having multiple if-instanceof-branches inside of bar

              • if you later want to make it work with TypeD, TypeE, ..., TypeZ, you don't have to dig into code of bar, you can simply supply yet another typeclass implementation

              • more importantly: if someone else wanted to use it with TypeD, TypeE, etc., then they could supply yet another typeclass implementation, without having to fork your bar implementation.


              In practice, the problem is that the typeclass instances won't be supplied automatically by the compiler, so it's usually not worth the hassle. Unless bar is somehow gigantic and super-complex, just overload it, or use instanceof.






              share|improve this answer














              In theory, nothing prevents you from using typeclasses for ad-hoc polymorphism in Java:



              interface Fooable<T> {
              int foo(T t, int second);
              }

              public int bar<T>(T t, int baz, Fooable<T> fooable) {
              int second = someCalculation(baz);
              return fooable.foo(t, second);
              }


              The implementations would look roughly as follows:



              public class TypeAFooable implements Fooable<TypeA> {
              public int foo(TypeA t, int second) { return yourLibrary.foo(t, second); }
              }


              And invocations would look like



              bar(myTypeAThing, 1234, new TypeAFooable());


              If bar were a little bit longer, this would bring several advantages:




              • if bar makes lots of calls to foo in lots of different places, then you could define each instance of the typeclass once, instead of having multiple if-instanceof-branches inside of bar

              • if you later want to make it work with TypeD, TypeE, ..., TypeZ, you don't have to dig into code of bar, you can simply supply yet another typeclass implementation

              • more importantly: if someone else wanted to use it with TypeD, TypeE, etc., then they could supply yet another typeclass implementation, without having to fork your bar implementation.


              In practice, the problem is that the typeclass instances won't be supplied automatically by the compiler, so it's usually not worth the hassle. Unless bar is somehow gigantic and super-complex, just overload it, or use instanceof.







              share|improve this answer














              share|improve this answer



              share|improve this answer








              edited Nov 20 at 20:33

























              answered Nov 20 at 20:14









              Andrey Tyukin

              26.3k42347




              26.3k42347























                  1














                  You can define first as a generic type type in bar as below.



                  bar(Object first, int baz) {
                  int second = someCalculation(baz);
                  if(first instanceOf TypeA) return foo((TypeA) first, second);
                  else if(first instanceOf TypeB) return foo((TypeB) first, second);
                  else if(first instanceOf TypeC) return foo((TypeC) first, second);
                  else throw new CustomException("Object pass in is not of correct type");
                  }





                  share|improve this answer




























                    1














                    You can define first as a generic type type in bar as below.



                    bar(Object first, int baz) {
                    int second = someCalculation(baz);
                    if(first instanceOf TypeA) return foo((TypeA) first, second);
                    else if(first instanceOf TypeB) return foo((TypeB) first, second);
                    else if(first instanceOf TypeC) return foo((TypeC) first, second);
                    else throw new CustomException("Object pass in is not of correct type");
                    }





                    share|improve this answer


























                      1












                      1








                      1






                      You can define first as a generic type type in bar as below.



                      bar(Object first, int baz) {
                      int second = someCalculation(baz);
                      if(first instanceOf TypeA) return foo((TypeA) first, second);
                      else if(first instanceOf TypeB) return foo((TypeB) first, second);
                      else if(first instanceOf TypeC) return foo((TypeC) first, second);
                      else throw new CustomException("Object pass in is not of correct type");
                      }





                      share|improve this answer














                      You can define first as a generic type type in bar as below.



                      bar(Object first, int baz) {
                      int second = someCalculation(baz);
                      if(first instanceOf TypeA) return foo((TypeA) first, second);
                      else if(first instanceOf TypeB) return foo((TypeB) first, second);
                      else if(first instanceOf TypeC) return foo((TypeC) first, second);
                      else throw new CustomException("Object pass in is not of correct type");
                      }






                      share|improve this answer














                      share|improve this answer



                      share|improve this answer








                      edited Nov 20 at 20:04

























                      answered Nov 20 at 20:01









                      Rishab Ghanti

                      312




                      312























                          1














                          I would attempt to avoid this problem by decomposing your bar() function into the piece that deals with computing int second and the piece that deals with TypeA/B/C first. That way you could write something like



                          int second = decomposedPortion(baz);
                          TypeR result = foo(first, second);





                          share|improve this answer


























                            1














                            I would attempt to avoid this problem by decomposing your bar() function into the piece that deals with computing int second and the piece that deals with TypeA/B/C first. That way you could write something like



                            int second = decomposedPortion(baz);
                            TypeR result = foo(first, second);





                            share|improve this answer
























                              1












                              1








                              1






                              I would attempt to avoid this problem by decomposing your bar() function into the piece that deals with computing int second and the piece that deals with TypeA/B/C first. That way you could write something like



                              int second = decomposedPortion(baz);
                              TypeR result = foo(first, second);





                              share|improve this answer












                              I would attempt to avoid this problem by decomposing your bar() function into the piece that deals with computing int second and the piece that deals with TypeA/B/C first. That way you could write something like



                              int second = decomposedPortion(baz);
                              TypeR result = foo(first, second);






                              share|improve this answer












                              share|improve this answer



                              share|improve this answer










                              answered Nov 20 at 20:16









                              Ben P.

                              22.3k31846




                              22.3k31846























                                  1














                                  We can replace the call of foo in bar by a call of a corresponding BiFunction. Thus for all overloaded foo methods a BiFunction has to be defined.



                                    private static final Map<Class<?>, BiFunction<?, Integer, TypeR>> FOO = Map.of(
                                  TypeA.class, (first, second) -> foo((TypeA) first, second),
                                  TypeB.class, (first, second) -> foo((TypeB) first, second),
                                  TypeC.class, (first, second) -> foo((TypeC) first, second));


                                  But for every overloaded foo mapping one line only has to be written whereas each overloaded bar method would need four lines if it were written as like in the question.



                                  Now we can make bar generic. But the following will not work, since the returned BiFunction has an unbound wildcard as first type parameter.



                                    <T> TypeR bar(T first, int baz) {
                                  int second = someCalculation(baz);
                                  return FOO.get(first.getClass()).apply(first, second);
                                  }


                                  We would need to declare FOO as Map<Class<T>, BiFunction<T, Integer, TypeR>> but that's not possible. To work around this we define a method with a type parameter T which is supposed to establish the missing type equality. But that's not for free. It's at the cost of a warning resulting from casting:



                                    private static <T> BiFunction<T, Integer, TypeR> fooOf(Object o) {
                                  return (BiFunction<T, Integer, TypeR>) FOO.get(o.getClass());
                                  }


                                  Now we can use this method in bar:



                                    <T> TypeR bar(T first, int baz) {
                                  int second = someCalculation(baz);
                                  return fooOf(first).apply(first, second);
                                  }


                                  This is similar to an instanceof approach but displaces the type distinction from the method bar to the Map FOO. If there are other methods than bar which also need to call foo in a similar way, the type distinction has not be coded again. FOO and fooOf can be reused. If the library changes and an additional overloaded TypeR foo(TypeD first, int second) gets introduced, only FOO needs to be updated by adding one additional line.



                                  This approach requires first to be not null.






                                  share|improve this answer




























                                    1














                                    We can replace the call of foo in bar by a call of a corresponding BiFunction. Thus for all overloaded foo methods a BiFunction has to be defined.



                                      private static final Map<Class<?>, BiFunction<?, Integer, TypeR>> FOO = Map.of(
                                    TypeA.class, (first, second) -> foo((TypeA) first, second),
                                    TypeB.class, (first, second) -> foo((TypeB) first, second),
                                    TypeC.class, (first, second) -> foo((TypeC) first, second));


                                    But for every overloaded foo mapping one line only has to be written whereas each overloaded bar method would need four lines if it were written as like in the question.



                                    Now we can make bar generic. But the following will not work, since the returned BiFunction has an unbound wildcard as first type parameter.



                                      <T> TypeR bar(T first, int baz) {
                                    int second = someCalculation(baz);
                                    return FOO.get(first.getClass()).apply(first, second);
                                    }


                                    We would need to declare FOO as Map<Class<T>, BiFunction<T, Integer, TypeR>> but that's not possible. To work around this we define a method with a type parameter T which is supposed to establish the missing type equality. But that's not for free. It's at the cost of a warning resulting from casting:



                                      private static <T> BiFunction<T, Integer, TypeR> fooOf(Object o) {
                                    return (BiFunction<T, Integer, TypeR>) FOO.get(o.getClass());
                                    }


                                    Now we can use this method in bar:



                                      <T> TypeR bar(T first, int baz) {
                                    int second = someCalculation(baz);
                                    return fooOf(first).apply(first, second);
                                    }


                                    This is similar to an instanceof approach but displaces the type distinction from the method bar to the Map FOO. If there are other methods than bar which also need to call foo in a similar way, the type distinction has not be coded again. FOO and fooOf can be reused. If the library changes and an additional overloaded TypeR foo(TypeD first, int second) gets introduced, only FOO needs to be updated by adding one additional line.



                                    This approach requires first to be not null.






                                    share|improve this answer


























                                      1












                                      1








                                      1






                                      We can replace the call of foo in bar by a call of a corresponding BiFunction. Thus for all overloaded foo methods a BiFunction has to be defined.



                                        private static final Map<Class<?>, BiFunction<?, Integer, TypeR>> FOO = Map.of(
                                      TypeA.class, (first, second) -> foo((TypeA) first, second),
                                      TypeB.class, (first, second) -> foo((TypeB) first, second),
                                      TypeC.class, (first, second) -> foo((TypeC) first, second));


                                      But for every overloaded foo mapping one line only has to be written whereas each overloaded bar method would need four lines if it were written as like in the question.



                                      Now we can make bar generic. But the following will not work, since the returned BiFunction has an unbound wildcard as first type parameter.



                                        <T> TypeR bar(T first, int baz) {
                                      int second = someCalculation(baz);
                                      return FOO.get(first.getClass()).apply(first, second);
                                      }


                                      We would need to declare FOO as Map<Class<T>, BiFunction<T, Integer, TypeR>> but that's not possible. To work around this we define a method with a type parameter T which is supposed to establish the missing type equality. But that's not for free. It's at the cost of a warning resulting from casting:



                                        private static <T> BiFunction<T, Integer, TypeR> fooOf(Object o) {
                                      return (BiFunction<T, Integer, TypeR>) FOO.get(o.getClass());
                                      }


                                      Now we can use this method in bar:



                                        <T> TypeR bar(T first, int baz) {
                                      int second = someCalculation(baz);
                                      return fooOf(first).apply(first, second);
                                      }


                                      This is similar to an instanceof approach but displaces the type distinction from the method bar to the Map FOO. If there are other methods than bar which also need to call foo in a similar way, the type distinction has not be coded again. FOO and fooOf can be reused. If the library changes and an additional overloaded TypeR foo(TypeD first, int second) gets introduced, only FOO needs to be updated by adding one additional line.



                                      This approach requires first to be not null.






                                      share|improve this answer














                                      We can replace the call of foo in bar by a call of a corresponding BiFunction. Thus for all overloaded foo methods a BiFunction has to be defined.



                                        private static final Map<Class<?>, BiFunction<?, Integer, TypeR>> FOO = Map.of(
                                      TypeA.class, (first, second) -> foo((TypeA) first, second),
                                      TypeB.class, (first, second) -> foo((TypeB) first, second),
                                      TypeC.class, (first, second) -> foo((TypeC) first, second));


                                      But for every overloaded foo mapping one line only has to be written whereas each overloaded bar method would need four lines if it were written as like in the question.



                                      Now we can make bar generic. But the following will not work, since the returned BiFunction has an unbound wildcard as first type parameter.



                                        <T> TypeR bar(T first, int baz) {
                                      int second = someCalculation(baz);
                                      return FOO.get(first.getClass()).apply(first, second);
                                      }


                                      We would need to declare FOO as Map<Class<T>, BiFunction<T, Integer, TypeR>> but that's not possible. To work around this we define a method with a type parameter T which is supposed to establish the missing type equality. But that's not for free. It's at the cost of a warning resulting from casting:



                                        private static <T> BiFunction<T, Integer, TypeR> fooOf(Object o) {
                                      return (BiFunction<T, Integer, TypeR>) FOO.get(o.getClass());
                                      }


                                      Now we can use this method in bar:



                                        <T> TypeR bar(T first, int baz) {
                                      int second = someCalculation(baz);
                                      return fooOf(first).apply(first, second);
                                      }


                                      This is similar to an instanceof approach but displaces the type distinction from the method bar to the Map FOO. If there are other methods than bar which also need to call foo in a similar way, the type distinction has not be coded again. FOO and fooOf can be reused. If the library changes and an additional overloaded TypeR foo(TypeD first, int second) gets introduced, only FOO needs to be updated by adding one additional line.



                                      This approach requires first to be not null.







                                      share|improve this answer














                                      share|improve this answer



                                      share|improve this answer








                                      edited Nov 20 at 22:48

























                                      answered Nov 20 at 22:22









                                      LuCio

                                      2,7391823




                                      2,7391823























                                          -1














                                          Use interfaces like this:



                                          interface Type { //...}

                                          class TypeA implements Type { //...}

                                          class TypeB implements Type { //...}

                                          class TypeC implements Type { //...}


                                          then you will only need one foo function



                                          foo(Type first, int second)



                                          and one bar function



                                          bar(Type first, int baz)






                                          share|improve this answer

















                                          • 1




                                            Yes, this would be a good design approach if the poster had the option. Unfortunately, the question states that the foo() methods are in a library.
                                            – Dave Costa
                                            Nov 20 at 19:57










                                          • They do not implement a common interface, and I have no controls over typeA to typeC or foo.
                                            – Anders
                                            Nov 20 at 19:57










                                          • how do you decide wich type must be used to call foo?
                                            – elbraulio
                                            Nov 20 at 20:00












                                          • I don't understand your question?
                                            – Anders
                                            Nov 20 at 20:07
















                                          -1














                                          Use interfaces like this:



                                          interface Type { //...}

                                          class TypeA implements Type { //...}

                                          class TypeB implements Type { //...}

                                          class TypeC implements Type { //...}


                                          then you will only need one foo function



                                          foo(Type first, int second)



                                          and one bar function



                                          bar(Type first, int baz)






                                          share|improve this answer

















                                          • 1




                                            Yes, this would be a good design approach if the poster had the option. Unfortunately, the question states that the foo() methods are in a library.
                                            – Dave Costa
                                            Nov 20 at 19:57










                                          • They do not implement a common interface, and I have no controls over typeA to typeC or foo.
                                            – Anders
                                            Nov 20 at 19:57










                                          • how do you decide wich type must be used to call foo?
                                            – elbraulio
                                            Nov 20 at 20:00












                                          • I don't understand your question?
                                            – Anders
                                            Nov 20 at 20:07














                                          -1












                                          -1








                                          -1






                                          Use interfaces like this:



                                          interface Type { //...}

                                          class TypeA implements Type { //...}

                                          class TypeB implements Type { //...}

                                          class TypeC implements Type { //...}


                                          then you will only need one foo function



                                          foo(Type first, int second)



                                          and one bar function



                                          bar(Type first, int baz)






                                          share|improve this answer












                                          Use interfaces like this:



                                          interface Type { //...}

                                          class TypeA implements Type { //...}

                                          class TypeB implements Type { //...}

                                          class TypeC implements Type { //...}


                                          then you will only need one foo function



                                          foo(Type first, int second)



                                          and one bar function



                                          bar(Type first, int baz)







                                          share|improve this answer












                                          share|improve this answer



                                          share|improve this answer










                                          answered Nov 20 at 19:55









                                          elbraulio

                                          4589




                                          4589








                                          • 1




                                            Yes, this would be a good design approach if the poster had the option. Unfortunately, the question states that the foo() methods are in a library.
                                            – Dave Costa
                                            Nov 20 at 19:57










                                          • They do not implement a common interface, and I have no controls over typeA to typeC or foo.
                                            – Anders
                                            Nov 20 at 19:57










                                          • how do you decide wich type must be used to call foo?
                                            – elbraulio
                                            Nov 20 at 20:00












                                          • I don't understand your question?
                                            – Anders
                                            Nov 20 at 20:07














                                          • 1




                                            Yes, this would be a good design approach if the poster had the option. Unfortunately, the question states that the foo() methods are in a library.
                                            – Dave Costa
                                            Nov 20 at 19:57










                                          • They do not implement a common interface, and I have no controls over typeA to typeC or foo.
                                            – Anders
                                            Nov 20 at 19:57










                                          • how do you decide wich type must be used to call foo?
                                            – elbraulio
                                            Nov 20 at 20:00












                                          • I don't understand your question?
                                            – Anders
                                            Nov 20 at 20:07








                                          1




                                          1




                                          Yes, this would be a good design approach if the poster had the option. Unfortunately, the question states that the foo() methods are in a library.
                                          – Dave Costa
                                          Nov 20 at 19:57




                                          Yes, this would be a good design approach if the poster had the option. Unfortunately, the question states that the foo() methods are in a library.
                                          – Dave Costa
                                          Nov 20 at 19:57












                                          They do not implement a common interface, and I have no controls over typeA to typeC or foo.
                                          – Anders
                                          Nov 20 at 19:57




                                          They do not implement a common interface, and I have no controls over typeA to typeC or foo.
                                          – Anders
                                          Nov 20 at 19:57












                                          how do you decide wich type must be used to call foo?
                                          – elbraulio
                                          Nov 20 at 20:00






                                          how do you decide wich type must be used to call foo?
                                          – elbraulio
                                          Nov 20 at 20:00














                                          I don't understand your question?
                                          – Anders
                                          Nov 20 at 20:07




                                          I don't understand your question?
                                          – Anders
                                          Nov 20 at 20:07


















                                          draft saved

                                          draft discarded




















































                                          Thanks for contributing an answer to Stack Overflow!


                                          • Please be sure to answer the question. Provide details and share your research!

                                          But avoid



                                          • Asking for help, clarification, or responding to other answers.

                                          • Making statements based on opinion; back them up with references or personal experience.


                                          To learn more, see our tips on writing great answers.





                                          Some of your past answers have not been well-received, and you're in danger of being blocked from answering.


                                          Please pay close attention to the following guidance:


                                          • Please be sure to answer the question. Provide details and share your research!

                                          But avoid



                                          • Asking for help, clarification, or responding to other answers.

                                          • Making statements based on opinion; back them up with references or personal experience.


                                          To learn more, see our tips on writing great answers.




                                          draft saved


                                          draft discarded














                                          StackExchange.ready(
                                          function () {
                                          StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53400523%2fpassing-an-argument-that-could-be-of-multiple-types-to-a-method-in-java%23new-answer', 'question_page');
                                          }
                                          );

                                          Post as a guest















                                          Required, but never shown





















































                                          Required, but never shown














                                          Required, but never shown












                                          Required, but never shown







                                          Required, but never shown

































                                          Required, but never shown














                                          Required, but never shown












                                          Required, but never shown







                                          Required, but never shown







                                          Popular posts from this blog

                                          404 Error Contact Form 7 ajax form submitting

                                          How to know if a Active Directory user can login interactively

                                          TypeError: fit_transform() missing 1 required positional argument: 'X'