In Delphi, you can overload functions, but doing so requires using the overload directive explicitly.
The following code declares two functions with the same name, one that will be invoked if you pass an integer, another that will be invoked you pass a string:
function MyFunc(a : Integer) : String; overload; function MyFunc(s : String) : String; overload;
In many other languages, the overload directive is implicit, you don’t have to type it and you can always overload.
On the other hand, it means that as long as your parameters differ, you can end up overloading an existing function without noticing, which can lead to confusion.
What do you think of function overloads?
- They're confusing, they shouldn't be allowed. (3%, 11 Votes)
- They can be useful, but should be explicit via a directive. (72%, 246 Votes)
- They're very useful, no directive should be required. (25%, 85 Votes)
Total Voters: 342
Loading ...
I think the best option would to be to support both constructs.
They are handy, but like anything can be abused into making code worse rather than better. Use with good judgement, hope for the best, maintain for readability.
@Linas
How so? You mean not requiring the directive, but accepting it just to maintain compatibility with existing code?
@Eric
That’s right. In such way you could choose which construct is more useful to you and also maintain compatibility with Delphi at the same time. Personally, if I would need to write a new code, I would use overloads without explicit directive, but it would also be nice to have compatibility with some old Delphi code.
In your example it is very clear which one gets called when you pass in a string or an integer. But if you overload it for example for all cases of signed and unsigned integer and even float types it can become confusing especially when one of them is missing and suddenly your integer argument is passed to one of the floating overloads. Had that in our logging library once and was wondering where that weird float value in the log came from.
Another example is the overloaded implicit class operators in TValue. Some of them are missing resulting in wrong results in some cases (see http://qc.embarcadero.com/wc/qcmain.aspx?d=96343)
I use them regularly, particularly when parsing XML. But I want the overload directive lest I mistakenly use the same function name that means something else in a large object. Maybe I’m not creative enough and I probably don’t spend enough time at the design stage, but when you have to dive in and fix something, the possibility of coming up with a same function name by mistake certainly exists. The lack of an overload has caught that problem for me on an occasion or two.
I think we’ve become lazy coders! Why wouldn’t I write an explicit overload after a function? Only reason is to save 8 keystrokes! is saving 8 keystrokes worth the hassle I might get f I add a function and not notice I am overloading and that leads to some hard to find bug because my code has subtly changed? Don’t think so.
They can be very handy and should not require a directive.
But if you have omitted the directive it should by default produce a warning.
@Steve
Why I have to type something that doesn’t make sense? If I’m writing a function with the same name and with different parameters I’m already overloading it. Of course compiler must not allow to overload functions with same parameters. Even if I didn’t notice that I was overloading a function, it won’t lead to new bugs because parameters are different so this new overloaded function will never be called unexpectedly. I don’t see why this can be confusing.
I believe that in order to preserve the elegance of Pascal, one should type the “overload” directive.
I think, the IDE must warn us when overloading without overload directive , but must compile without it , Just like virtual and override keywords in c#.
It will prevent us from accident overloading with methods which are completely different from the previous one (declaring without knowing that there is a method with the same name to do a different task)
This will increase the good practice of coding in the Delphi community.
So what i feel is explicit declaration is not wrong but some freedom must be also given.
I picked 2, even though I think they’re very useful. Explicitly adding the directive makes the intent clear and avoids accidentally overloading a method.
i would prefer delphi standards.
how about extend it to:
function MyFunc(a: Integer): String; overload;
function MyFunc(a: Integer): Integer; overload;
They’re /very/ useful, but I think the keyword should be required for a clean compile.
One alternative would be to not require the directive, but warn if a variable, method, or property name clashes with an identifier in ancestor classes. In that case, the directive could be used to quiet the warning.
I’m not sure I like it though. 🙂 I think at least warning (if not failing) on any undecorated overload makes the most sense.
@Linas
That is not true. You can overload methods with the same number of arguments but with different types. Introducing an overload with a better matching type will result in calling this new method instead of the existing one.
@dennis
That could only work when functions are not allowed to be called without assigning the result (I don’t remember the compiler switch but there is one that is off by default). What if the result is assigned to a type that is assignment compatible to both result types?
I prefer the explicit declaration. I think it is better to err on the side of explicitness in order to increase clarity of code.
Hi Eric!
In Free Pascal when using mode “ObjFPC” it is already allowed to leave away the “overload” (globally as well as in objects/records).
Note: It is important however if you overload functions/procedures that are defined in different units.
E.g. Unit A defines “MyProc(String)” and unit B “MyProc(Integer)”. If unit B is placed after unit A you can not use “MyProc(‘Hello World’)” as long as “MyProc(Integer)” isn’t declared with “overload” (or you use “A.MyProc(‘Hello World’)” of course). You don’t need to declare “MyProc(String)” as overload though.
Regards,
Sven
Leave it that way. If you are overloading, you have to say that using the directive.
Overloads are an important part of Delphi…. so of course they’re often heavily abused.
I use overloads quite often, where an operation can support multiple Types (such as Method Types “of Object” and Method Types NOT “of Object”).
I think implicit overloading would be dangerous… as developers would end up inadvertantly overloading methods, and it would lead to quite a lot of confusion.
@Stefan
-> compiler error. if it’s not 100% clear which function should be used then throw an error.
give an example, I can’t think of any, could be solves with the “as” statement:
MyResult := MyFunc(bla,bla) as TMyResult;
Let’s see the choices:
– if you like option 1 (shouldn’t be allowed), you can live well with option 2 (like it is today) and never type overload. The compiler will yell at you if you reuse an existing name for a routine and you’ll have to rename your routine. Option 3 will be a nightmare for you…
– if you like option 2 (explicit directive, my choice), option 1 removes unnecessarily (see above) a feature that can be useful (if used right) and breaks compatibility with existing code (baaad). Option 3 breaks introduces (only for code typing laziness) ambiguity and unreadability even worse than the infamous “with”.
– if you like overloading so much that you choose option 3 (implicit), option 1 would prevent you from even doing it, while option 2 allows you to do it as much as you want provided you can do 10 extra keystrokes.
Bottom line: option2 is the only one that makes sense because it is a compromise that works more or less for everybody. CQFD!
@dennis
You know that as is only available for class types, right?
I doubt it is possible without the explicit declaration. If a (non-method) function is declared in a different unit, it usually hides any identifiers declared “earlier”. Only with overload, they can exist side by side.
The same for methods: a method with the same name, but declared in a derivate class, will hide the method in the original class. Only with an explicit overload directive, they can co-exist in the same class.
The explicit directive is, IMO, also a lot clearer and beats what e.g. C++ users have to do to achieve the same (“using”).
@stefan: sure, but dws might use it for data types as well…
+1 for directive required
-1 for without directive
I’ve just clicked the wrong one.
François said exactly what I think.