scalaoverloading

Why "avoid method overloading"?


Why does Jorge Ortiz advise to avoid method overloading?


Solution

  • Overloading makes it a little harder to lift a method to a function:

    object A {
       def foo(a: Int) = 0
       def foo(b: Boolean) = 0
       def foo(a: Int, b: Int) = 0
    
       val function = foo _ // fails, must use = foo(_, _) or (a: Int) => foo(a)
    }
    

    You cannot selectively import one of a set of overloaded methods.

    There is a greater chance that ambiguity will arise when trying to apply implicit views to adapt the arguments to the parameter types:

    scala> implicit def S2B(s: String) = !s.isEmpty                             
    S2B: (s: String)Boolean
    
    scala> implicit def S2I(s: String) = s.length                               
    S2I: (s: String)Int
    
    scala> object test { def foo(a: Int) = 0; def foo(b: Boolean) = 1; foo("") }
    <console>:15: error: ambiguous reference to overloaded definition,
    both method foo in object test of type (b: Boolean)Int
    and  method foo in object test of type (a: Int)Int
    match argument types (java.lang.String)
           object test { def foo(a: Int) = 0; def foo(b: Boolean) = 1; foo("") }
    

    It can quietly render default parameters unusable:

    object test { 
        def foo(a: Int) = 0; 
        def foo(a: Int, b: Int = 0) = 1 
    }
    

    Individually, these reasons don't compel you to completely shun overloading. I feel like I'm missing some bigger problems.

    UPDATE

    The evidence is stacking up.

    UPDATE 2

    UPDATE 3

    scala> object O { def apply[T](ts: T*) = (); def apply(f: (String => Int)) = () }
    defined object O
    
    scala> O((i: String) => f(i)) // oops, I meant to call the second overload but someone changed the return type of `f` when I wasn't looking...