Just curious is there any technical limitation in having multiple return values for methods in languages like java, c, c++ or limitation is just by spec? In assembly language I understand callee can pop one value to register.
Because in the days of C there is/was a single register used to hold the return value.
Because if you need more values, you can just return a struct, reference (in Java/C#), or pointer.
Because you can use an out parameter.
Allowing multiple return values would add complexity, and it's simply worked around. There's no reason for it to be there. (Indeed, in C++ you can return a tuple (from TR1, C++11, or boost) which effectively is multiple return values)
Its by design, because there is no need to allow multiple values in return statement. You can always define a struct with all the needed members, and create an instance of the struct and return it. Simple!
Example,
struct Person
{
std::string Name;
int Age;
std::string Qualification;
//...
};
Person GetInfo()
{
Person person;
//fill person's members ...
return person;
}
You can use std::pair, std::vector, std::map, std::list and so on. In C++0x, you can use std::tuple as well.
If the Genie gave you only one wish, you could just wish to have any number of wishes. It's the same with just one return value from a method. You can use your return value as a pointer to an address where an object full of attributes resides and then query those attributes (properties)... This way there really is no limitation. :-)
Fun coding and many happy returns :-)
It's just a decision and because people are used to it. In principle there wouldn't be anything preventing a language designer from implementing a syntax like this:
(int, int, int) call(int x, int y, int z);
and a function call could look like this:
(a, b, c) = call(1, 2, 3);
or whatever syntax they would choose for this task. Though one could discuss if it would add to readability. And as others have pointed out, some languages implement this by tuples or similar constructs.
Sure, the return statement:
(int, int, int) call(int x, int y, int z);
{
return x+1, y+1, z+1
}
You could even think of useful applications like:
(err, filehandle) = OpenFileDialog(...)
where the function can return either a detailed error code or a valid file handle. Though exceptions take this place nowadays. But exceptions are in some sense a way to return at least two alternating values, either the requested function return value or the raised exception.
Because good programming languages encourage programmers to do the right thing. If a method needs to return multiple values, those values probably are related, and thus should be group together in something like a struc.
Just my 2 cents.
It's mostly due to historical reasons having to do with machine calling conventions. Also because C doesn't have a pattern matching syntax on the callee side to retrieve the results. Note that languages like ML or Haskell have a syntactically lightweight tuple type that is perfectly usable for returning multiple values.
Edited:
Actually thinking about it a little bit, I guess if you wanted to split hairs, ML and Haskell still have a "single" return value. It's just that tuples are so lightweight syntactically that it's convenient to think about functions returning multiple values rather than a single tuple.
To be totally rigorous, there are two languages that I can think of that have "proper" multiple-values returns that are not just tuples in some shape. One is Scheme, (c.f call-with-values), and the other is MATLAB:
function [x,y] = myFunc(a, b)
...
end
[p, q] = myFunc(3,4)
In both of these languages, there is a special syntactic distinction between a single value that happens to be an aggregate (cons cell, array, respectively) and multiple values.
It's just a decision made by the language and/or ABI designers. No more, no less. In assembly language, you can make those decisions yourself, though - I'm not sure what your last comment means.
We don't need the ability to return multiple values built into the C++ language, because the library works just fine:
std::tuple<int,float> func()
{
return std::make_tuple(1, 2.f);
}
int i;
float f;
std::tie(i, f) = func();
Most other languages have similar functionality in their standard library.
Actually, there are at least 2 ways to return multiple values.
First is to return create a struct or class, put all the return data, and return it.
second is to pass parameters by reference (non-const) and put the values in there.
It is useful to support this, and given how people find it convenient in other languages, C and Java may move that way too.
C++ is already standardising on the kind of convenient, intuitive handling of return values familiar from e.g. Ruby and python for the function-caller side, which is more important than at the return itself, because a single function is likely called from a great many call sites.
Specifically, the C++17 paper here (see also wording here) documents a notation...
auto [x,y,z] = expression;
...where expression can be a function returning - or any other expression evaluating to - an array, a tuple, or a struct with all public members. The above can be preceded by const to make the local variables const.
The feature also documents this...
for (const auto& [key,value] : mymap)
...
...which avoids repeated use of the less-expressive ->first and ->second.
With C++ moving in this direction, it's likely C and other C-derived languages will look carefully at doing likewise.
Related
I thought only functions had return statements since they were explicitly called whereas methods are implicitly called on the class. However, I have seen examples of code where a method has a return statement. Is this conventional? Also, am I wrong in saying that only functions return values, and are methods having return statements a standard convention across multiple languages of only OOP languages?
A method is a function that is associated with an object (or class). So yes, they can return values, or not.
Also - trying things out yourself and/or reading documentation is a much better way to learn than asking us as soon as you get stuck! ;)
Here is Oracle's documentation for defining methods.
I think this is problems of theory. Let me put clear some points.
Before OOP
procedures was a bits of programs for do someting
functions was a bits of programs for do someting and return values, like Math f(x) = x*y+E2
After OOP
procedures and functions are called methods and is equal if they return or not some value.
PD: Also we have methods:
with firm: function A(b,x) { ... }
without firm: function A() { ... }
anoimate: function () { ... }
The post contains incorrect assumptions. For starters Java only has "methods (in this context), even if static. Given this it is trivially true that methods at large in Java can return a value.
Now, as an example1, for an equivalency with a language like VB.NET (which derives from BASIC),
A method that returns a value is a "Function Procedure" (BASIC lingo) - these methods return a value and can then be used as an appropriately-typed expression. They must contain a return statement on all possible code-execution paths.
A method that has a void return type is a "Sub Procedure" (BASIC lingo) - these methods do not (and cannot) return a value. Such methods may only be called as statements.
1 The terms "function", "procedure", and "subroutine", eg, are highly dependent upon language/context which is why the above is prefaced. As such, correct Java-terminology dictates using "methods [returning some value upon completion]" and "void methods" to describe the difference - although I find that "function" is still used colloquially (in my circles) when describing the operation of "computing a value without side effects" or when such is supplied as a higher-order argument (eg. lambdas).
Methods can have return statements as long as the return type is not void. When you define the method, you can make the method public or private, static or not static, choose the return type (byte, short, int, long, float, double, boolean, char), name the method, and define the inputs.
`public static returnType methodName(input) {
// body
}`
My questions are motivated by a C++ code which is not mine and that I am currently trying to understand. Nevertheless, I think this question can be answered by OO developers in general (because I have ever seen this case in Java code for example).
Reading through the code, I noticed that the developer always work using side effects (most functions have "void return type" except for getters and some rare cases) instead of returning results directly. He sometimes uses return values but only for control flows (error code... instead of exceptions).
Here are two possible examples of his prototypes (in pseudo-code):
For a function that should return min, max and avg of the float values in a matrix M:
void computeStatistics(float min, float max, float avg, Matrix M);
OR
void computeStatistics(List myStat, Matrix M);
For a function that should return some objects in a given list that verifies a certain criteria and the number of objects found:
int controlValue findObjects(List result, int nbObjectsFound, Object myCriteria, List givenList)
I am not familiar with C++ as you can probably see in my very-pseudo-code... But rather with Matlab where it is possible to return everything you want from a function for example an int and a List side by side (which could be useful for the second example). I know it is not possible in C++ and that could explain the second prototype but it doesn't explain the choice for the first example where he could have done:
List myStat computeStat(Matrix M)
Finally, here are my questions:
What are the possible reasons that could motivate this choice? Is it a good practice, a convention or just a development choice? Are there advantages of one way over the other (returning values vs. side effects way)?
In terms of C++:
IMO using returns values is clearer than passing value by references and present, in most cases, no overhead. (please have a look at RVO and Copy Elision)
However if you do use return values for your control flow, using references is not a bad thing and is still clear for most developers.
So I guess we could say that the choice is yours.
Keep also in mind that many developers are not aware of what black magic your C++ compiler is doing and so using return values might offend them.
In the past it was a common practice to use reference parameters as output, since returning complex objects was very slow without return value optimization an move semantic. Today I belief in most cases returning the value is the best choice.
Want Speed? Pass by Value.
Writing the following provided that the list has a copy would by me be considered inappropriate.
void computeStatistics(List myStat, Matrix M);
Instead (provided that list has copy) you should.
List myStat computeStat(Matrix M)
However the call-by-reference approach can be motivated if you do not have a copy on your object, then you wont need to allocate it on the heap instead you can allocate it on the stack and send your function a pointer to it.
Regarding:
void computeStatistics(float min, float max, float avg, Matrix M);
My personal opinion is that best-practice is one method one purpose, so I would do this like:
float min computeMin(Matrix M);
float max computeMax(Matrix M);
float avg computeAvg(Matrix M);
The only reason that I can see for making all this in one function would be because the calculations are not done separately (more work to do it in separate functions).
If you however need to have several return types in one method i would do it with call-by-reference. For example:
void SomeMethod(input1, input2, &output1, &output2, &output3)
Recently I refactored the code of a 3rd party hash function from C++ to C. The process was relatively painless, with only a few changes of note. Now I want to write the same function in Java and I came upon a slight issue.
In the C/C++ code there is a C preprocessor macro that takes a few integer variables names as arguments and performs a bunch of bitwise operations with their contents and a few constants. That macro is used in several different places, therefore its presence avoids a fair bit of code duplication.
In Java, however, there is no equivalent for the C preprocessor. There is also no way to affect any basic type passed as an argument to a method - even autoboxing produces immutable objects. Coupled with the fact that Java methods return a single value, I can't seem to find a simple way to rewrite the macro.
Avenues that I considered:
Expand the macro by hand everywhere: It would work, but the code duplication could make things interesting in the long run.
Write a method that returns an array: This would also work, but it would repeatedly result into code like this:
long tmp[] = bitops(k, l, m, x, y, z);
k = tmp[0];
l = tmp[1];
m = tmp[2];
x = tmp[3];
y = tmp[4];
z = tmp[5];
Write a method that takes an array as an argument: This would mean that all variable names would be reduced to array element references - it would be rather hard to keep track of which index corresponds to which variable.
Create a separate class e.g. State with public fields of the appropriate type and use that as an argument to a method: This is my current solution. It allows the method to alter the variables, while still keeping their names. It has the disadvantage, however, that the State class will get more and more complex, as more macros and variables are added, in order to avoid copying values back and forth among different State objects.
How would you rewrite such a C macro in Java? Is there a more appropriate way to deal with this, using the facilities provided by the standard Java 6 Development Kit (i.e. without 3rd party libraries or a separate preprocessor)?
Option 3, create you own MutableInteger wrapper class.
struct MutableInteger{
public MutableInteger(int v) { this.value = value;}
public int value;
}
public void swap3( MutableInteger k, MutableInteger l, MutableInteger m) {
int t = m.value;
m.value = l.value
l.value=k.value;
k.value=t;
}
Create a separate class e.g. State
with public fields of the appropriate
type and use that as an argument to a
method
This, but as an intermediate step. Then continue refactoring - ideally class State should have private fields. Replace the macros with methods to update this state. Then replace all the rest of your code with methods that update the state, until eventually your program looks like:
System.out.println(State(System.in).hexDigest());
Finally, rename State to SHA1 or whatever ;-)
One of my most common bugs is that I can never remember whether something is a method or a property, so I'm constantly adding or removing parentheses.
So I was wondering if there was good logic behind making the difference between calling on an object's properties and methods explicit.
Obviously, it allows you to have properties and methods that share the same name, but I don't think that comes up much.
The only big benefit I can come up with is readability. Sometimes you might want to know whether something is a method or a property while you're looking at code, but I'm having trouble coming up with specific examples when that would be really helpful. But I am a n00b, so I probably just haven't encountered such a situation yet. I'd appreciate examples of such a situation.
Also, are there other languages where the difference isn't explicit?
Anyways, if you could answer, it will help me be less annoyed every time I make this mistake ^-^.
UPDATE:
Thanks everyone for the awesome answers so far! I only have about a week's worth of js, and 1 day of python, so I had no idea you could reference functions without calling them. That's awesome. I have a little more experience with java, so that's where I was mostly coming from... can anyone come up with an equally compelling argument for that to be the case in java, where you can't reference functions? Aside from it being a very explicit language, with all the benefits that entails :).
All modern languages require this because referencing a function and calling a function are separate actions.
For example,
def func():
print "hello"
return 10
a = func
a()
Clearly, a = func and a = func() have very different meanings.
Ruby--the most likely language you're thinking of in contrast--doesn't require the parentheses; it can do this because it doesn't support taking references to functions.
In languages like Python and JavaScript, functions are first–class objects. This means that you can pass functions around, just like you can pass around any other value. The parentheses after the function name (the () in myfunc()) actually constitute an operator, just like + or *. Instead of meaning "add this number to another number" (in the case of +), () means "execute the preceding function". This is necessary because it is possible to use a function without executing it. For example, you may wish to compare it to another function using ==, or you may wish to pass it into another function, such as in this JavaScript example:
function alertSomething(message) {
alert(message);
}
function myOtherFunction(someFunction, someArg) {
someFunction(someArg);
}
// here we are using the alertSomething function without calling it directly
myOtherFunction(alertSomething, "Hello, araneae!");
In short: it is important to be able to refer to a function without calling it — this is why the distinction is necessary.
At least in JS, its because you can pass functions around.
var func = new Function();
you can then so something like
var f = func
f()
so 'f' and 'func' are references to the function, and f() or func() is the invocation of the function.
which is not the same as
var val = f();
which assigns the result of the invocation to a var.
For Java, you cannot pass functions around, at least like you can in JS, so there is no reason the language needs to require a () to invoke a method. But it is what it is.
I can't speak at all for python.
But the main point is different languages might have reasons why syntax may be necessary, and sometimes syntax is just syntax.
I think you answered it yourself:
One of my most common bugs is that I can never remember whether something is a method or a property, so I'm constantly adding or removing parentheses.
Consider the following:
if (colorOfTheSky == 'blue')
vs:
if (colorOfTheSky() == 'blue')
We can tell just by looking that the first checks for a variable called colorOfTheSky, and we want to know if its value is blue. In the second, we know that colorOfTheSky() calls a function (method) and we want to know if its return value is blue.
If we didn't have this distinction it would be extremely ambiguous in situations like this.
To answer your last question, I don't know of any languages that don't have this distinction.
Also, you probably have a design problem if you can't tell the difference between your methods and your properties; as another answer points out, methods and properties have different roles to play. Furthermore it is good practice for your method names to be actions, e.g. getPageTitle, getUserId, etc., and for your properties to be nouns, e.g., pageTitle, userId. These should be easily decipherable in your code for both you and anyone who comes along later and reads your code.
If you're having troubles, distinguishing between your properties and methods, you're probably not naming them very well.
In general, your methods should have a verb in them: i.e. write, print, echo, open, close, get, set, and property names should be nouns or adjectives: name, color, filled, loaded.
It's very important to use meaningful method and property names, without it, you'll find that you'll have difficulty reading your own code.
In Java, I can think of two reasons why the () is required:
1) Java had a specific design goal to have a "C/C++ like" syntax, to make it easy for C and C++ programmers to learn the language. Both C and C++ require the parentheses.
2) The Java syntax specifically requires the parentheses to disambiguate a reference to an attribute or local from a call to a method. This is because method names and attribute / local names are declared in different namespaces. So the following is legal Java:
public class SomeClass {
private int name;
private int name() { ... }
...
int norm = name; // this one
}
If the () was not required for a method call, the compiler would not be able to tell if the labeled statement ("this one") was assigning the value of the name attribute or the result of calling the name() method.
The difference isn't always explicit in VBA. This is a call to a Sub (i.e. a method with no return value) which takes no parameters (all examples are from Excel):
Worksheets("Sheet1").UsedRange.Columns.AutoFit
whereas this is accessing an attribute then passing it as a parameter:
MsgBox Application.Creator
As in the previous example, parentheses are also optional around parameters if there is no need to deal with the return value:
Application.Goto Worksheets("Sheet2").Range("A1")
but are needed if the return value is used:
iRows = Len("hello world")
Because referencing and calling a method are two different things. Consider X.method being the method of class X and x being an instance of X, so x.method == 'blue' would'nt ever be able to be true because methods are not strings.
You can try this: print a method of an object:
>>> class X(object):
... def a(self):
... print 'a'
...
>>> x=X()
>>> print x.a
<bound method X.a of <__main__.X object at 0x0235A910>>
Typically properties are accessors, and methods perform some sort of action. Going on this assumption, it's cheap to use a property, expensive to use a method.
Foo.Bar, for example, would indicate to me that it would return a value, like a string, without lots of overhead.
Foo.Bar() (or more likely, Foo.GetBar()), on the other hand, implies needing to retrieve the value for "Bar", perhaps from a database.
Properties and methods have different purposes and different implications, so they should be differentiated in code as well.
By the way, in all languages I know of the difference in syntax is explicit, but behind the scenes properties are often treated as simply special method calls.
Occasionally , we have to write methods that receive many many arguments , for example :
public void doSomething(Object objA , Object objectB ,Date date1 ,Date date2 ,String str1 ,String str2 )
{
}
When I encounter this kind of problem , I often encapsulate arguments into a map.
Map<Object,Object> params = new HashMap<Object,Object>();
params.put("objA",ObjA) ;
......
public void doSomething(Map<Object,Object> params)
{
// extracting params
Object objA = (Object)params.get("objA");
......
}
This is not a good practice , encapsulate params into a map is totally a waste of efficiency.
The good thing is , the clean signature , easy to add other params with fewest modification .
what's the best practice for this kind of problem ?
In Effective Java, Chapter 7 (Methods), Item 40 (Design method signatures carefully), Bloch writes:
There are three techniques for shortening overly long parameter lists:
break the method into multiple methods, each which require only a subset of the parameters
create helper classes to hold group of parameters (typically static member classes)
adapt the Builder pattern from object construction to method invocation.
For more details, I encourage you to buy the book, it's really worth it.
Using a map with magical String keys is a bad idea. You lose any compile time checking, and it's really unclear what the required parameters are. You'd need to write very complete documentation to make up for it. Will you remember in a few weeks what those Strings are without looking at the code? What if you made a typo? Use the wrong type? You won't find out until you run the code.
Instead use a model. Make a class which will be a container for all those parameters. That way you keep the type safety of Java. You can also pass that object around to other methods, put it in collections, etc.
Of course if the set of parameters isn't used elsewhere or passed around, a dedicated model may be overkill. There's a balance to be struck, so use common sense.
If you have many optional parameters you can create fluent API: replace single method with the chain of methods
exportWithParams().datesBetween(date1,date2)
.format("xml")
.columns("id","name","phone")
.table("angry_robots")
.invoke();
Using static import you can create inner fluent APIs:
... .datesBetween(from(date1).to(date2)) ...
It's called "Introduce Parameter Object". If you find yourself passing same parameter list on several places, just create a class which holds them all.
XXXParameter param = new XXXParameter(objA, objB, date1, date2, str1, str2);
// ...
doSomething(param);
Even if you don't find yourself passing same parameter list so often, that easy refactoring will still improve your code readability, which is always good. If you look at your code 3 months later, it will be easier to comprehend when you need to fix a bug or add a feature.
It's a general philosophy of course, and since you haven't provided any details, I cannot give you more detailed advice either. :-)
First, I'd try to refactor the method. If it's using that many parameters it may be too long any way. Breaking it down would both improve the code and potentially reduce the number of parameters to each method. You might also be able to refactor the entire operation to its own class. Second, I'd look for other instances where I'm using the same (or superset) of the same parameter list. If you have multiple instances, then it likely signals that these properties belong together. In that case, create a class to hold the parameters and use it. Lastly, I'd evaluate whether the number of parameters makes it worth creating a map object to improve code readability. I think this is a personal call -- there is pain each way with this solution and where the trade-off point is may differ. For six parameters I probably wouldn't do it. For 10 I probably would (if none of the other methods worked first).
This is often a problem when constructing objects.
In that case use builder object pattern, it works well if you have big list of parameters and not always need all of them.
You can also adapt it to method invocation.
It also increases readability a lot.
public class BigObject
{
// public getters
// private setters
public static class Buider
{
private A f1;
private B f2;
private C f3;
private D f4;
private E f5;
public Buider setField1(A f1) { this.f1 = f1; return this; }
public Buider setField2(B f2) { this.f2 = f2; return this; }
public Buider setField3(C f3) { this.f3 = f3; return this; }
public Buider setField4(D f4) { this.f4 = f4; return this; }
public Buider setField5(E f5) { this.f5 = f5; return this; }
public BigObject build()
{
BigObject result = new BigObject();
result.setField1(f1);
result.setField2(f2);
result.setField3(f3);
result.setField4(f4);
result.setField5(f5);
return result;
}
}
}
// Usage:
BigObject boo = new BigObject.Builder()
.setField1(/* whatever */)
.setField2(/* whatever */)
.setField3(/* whatever */)
.setField4(/* whatever */)
.setField5(/* whatever */)
.build();
You can also put verification logic into Builder set..() and build() methods.
There is a pattern called as Parameter object.
Idea is to use one object in place of all the parameters. Now even if you need to add parameters later, you just need to add it to the object. The method interface remains same.
You could create a class to hold that data. Needs to be meaningful enough though, but much better than using a map (OMG).
Code Complete* suggests a couple of things:
"Limit the number of a routine's parameters to about seven. Seven is a magic number for people's comprehension" (p 108).
"Put parameters in input-modify-output order ... If several routines use similar parameters, put the similar parameters in a consistent order" (p 105).
Put status or error variables last.
As tvanfosson mentioned, pass only the parts of a structured variables ( objects) that the routine needs. That said, if you're using most of the structured variable in the function, then just pass the whole structure, but be aware that this promotes coupling to some degree.
* First Edition, I know I should update. Also, it's likely that some of this advice may have changed since the second edition was written when OOP was beginning to become more popular.
Using a Map is a simple way to clean the call signature but then you have another problem. You need to look inside the method's body to see what the method expects in that Map, what are the key names or what types the values have.
A cleaner way would be to group all parameters in an object bean but that still does not fix the problem entirely.
What you have here is a design issue. With more than 7 parameters to a method you will start to have problems remembering what they represent and what order they have. From here you will get lots of bugs just by calling the method in wrong parameter order.
You need a better design of the app not a best practice to send lots of parameters.
Good practice would be to refactor. What about these objects means that they should be passed in to this method? Should they be encapsulated into a single object?
Create a bean class, and set the all parameters (setter method) and pass this bean object to the method.
Look at your code, and see why all those parameters are passed in. Sometimes it is possible to refactor the method itself.
Using a map leaves your method vulnerable. What if somebody using your method misspells a parameter name, or posts a string where your method expects a UDT?
Define a Transfer Object . It'll provide you with type-checking at the very least; it may even be possible for you to perform some validation at the point of use instead of within your method.
I would say stick with the way you did it before.
The number of parameters in your example is not a lot, but the alternatives are much more horrible.
Map - There's the efficiency thing that you mentioned, but the bigger problem here are:
Callers don't know what to send you without referring to something
else... Do you have javadocs which states exactly what keys and
values are used? If you do (which is great), then having lots of parameters
isn't a problem either.
It becomes very difficult to accept different argument types. You
can either restrict input parameters to a single type, or use
Map<String, Object> and cast all the values. Both options are
horrible most of the time.
Wrapper objects - this just moves the problem since you need to fill the wrapper object in the first place - instead of directly to your method, it will be to the constructor of the parameter object.
To determine whether moving the problem is appropriate or not depends on the reuse of said object. For instance:
Would not use it: It would only be used once on the first call, so a lot of additional code to deal with 1 line...?
{
AnObject h = obj.callMyMethod(a, b, c, d, e, f, g);
SomeObject i = obj2.callAnotherMethod(a, b, c, h);
FinalResult j = obj3.callAFinalMethod(c, e, f, h, i);
}
May use it: Here, it can do a bit more. First, it can factor the parameters for 3 method calls. it can also perform 2 other lines in itself... so it becomes a state variable in a sense...
{
AnObject h = obj.callMyMethod(a, b, c, d, e, f, g);
e = h.resultOfSomeTransformation();
SomeObject i = obj2.callAnotherMethod(a, b, c, d, e, f, g);
f = i.somethingElse();
FinalResult j = obj3.callAFinalMethod(a, b, c, d, e, f, g, h, i);
}
Builder pattern - this is an anti-pattern in my view. The most desirable error handling mechanism is to detect earlier, not later; but with the builder pattern, calls with missing (programmer did not think to include it) mandatory parameters are moved from compile time to run time. Of course if the programmer intentionally put null or such in the slot, that'll be runtime, but still catching some errors earlier is a much bigger advantage to catering for programmers who refuse to look at the parameter names of the method they are calling.
I find it only appropriate when dealing with large number of optional parameters, and even then, the benefit is marginal at best. I am very much against the builder "pattern".
The other thing people forget to consider is the role of the IDE in all this.
When methods have parameters, IDEs generate most of the code for you, and you have the red lines reminding you what you need to supply/set. When using option 3... you lose this completely. It's now up to the programmer to get it right, and there's no cues during coding and compile time... the programmer must test it to find out.
Furthermore, options 2 and 3, if adopted wide spread unnecessarily, have long term negative implications in terms of maintenance due to the large amount of duplicate code it generates. The more code there is, the more there is to maintain, the more time and money is spent to maintain it.
This is often an indication that your class holds more than one responsibility (i.e., your class does TOO much).
See The Single Responsibility Principle
for further details.
If you are passing too many parameters then try to refactor the method. Maybe it is doing a lot of things that it is not suppose to do. If that is not the case then try substituting the parameters with a single class. This way you can encapsulate everything in a single class instance and pass the instance around and not the parameters.
... and Bob's your uncle: No-hassle fancy-pants APIs for object creation!
https://projectlombok.org/features/Builder