I need to return 2 values from a method. My approach is as follows:
- create an inner class with 2 fields that will be used to keep those 2 values
- put the method inside that class
- instantiate the class and call the method.
The only thing that will be changed in the method is that in the end it will assign those 2 values to the fields of the instance. Then I can address those values by referencing to the fields of that object.
Is it a good design and why?
3
I would argue this along the following lines:
- Why exactly does your method return multiple values? What kind of cohesion are we talking about – should those values actually be fields on a single class, or are they just coincidentally returned by the same method, but otherwise unrelated? If it’s the latter, you might want to consider splitting the method into two methods, rather. Edit: use your judgement here; sometimes a type of “coincidental” cohesion may be the best option. Another option is to use a pair or tuple construct, although in OOP, these are usually not seen in public APIs (some notable exceptions being standard collections, etc).
- If the values do deserve to form a class, I would probably advise against using an inner class. Inner classes are typically used as internal implementation details, which are hidden from the outside. Is there any reason why this result shouldn’t be a “full-blown” class, in its own right?
- Other than holding data, what operations are applicable to this new class? In object oriented design, you want to have the related behaviour close to the relevant data (which seem to be your intentions, too). Should the method you are referring to not live on this class rather?
To summarise, I would see if I can turn this “data object” into a fledged-out class with both data and behaviour. As an additional comment, you may want to make the class immutable, since its state is set once. Making it immutable will help prevent it being incorrectly set, or modified later (say, someone setting one of the fields to null and passing it along).
Edit: As Patkos Csaba correctly points out, the principle being applied here is the Single Responsibility Principle (SRP) – the class you are trying to create should really have one responsibility (defined as a reason for changing). This design guideline should help you figure out whether your two fields belong in a single class, or not. To stick with the Wikipedia example, your class could be a seen as a type of report, in which case it’s conforming to SRP, but it’s difficult to comment without further information.
16
There’s the concept of a Tuple which is featured in other languages, such as Python.
One could return an instance of this genericized class which is easily re-usable:
public class TypedTuple<L, R> implements Serializable {
private static final long serialVersionUID = 1L;
protected L left;
protected R right;
protected TypedTuple() {
// Default constructor for serialization
}
public TypedTuple(L inLeft, R inRight) {
left = inLeft;
right = inRight;
}
public L getLeft() {
return left;
}
public R getRight() {
return right;
}
}
1
It seems that this class is taking responsibility away from another class, and this makes me think that this design isn’t great.
For a method that returns multible values, I would rather
- return a generic containter (e.g. a List or Map) containing the return values
or
- create a Class for the return value, which contains just of the necessary fields + getters + a constructor with all fields
Example for the second option:
public Class FooBarRetval {
private String foo;
private int bar;
public FooBarRetval (String foo, int bar) {
this.foo = foo;
this.bar = bar;
}
public String getFoo() {
return foo;
}
public int getBar() {
return bar;
}
}
4
Putting multiple return values from a method into its own class/structure is often used in message based systems that have one class for
Request and response. An example of this is Simple Object Access Protocol (SOAP).
Is it a good design and why?
At least it is quite common. If this is good or bad depends on your special usecase.
Short answer: You can return an array or a List with the two values.
I personally would write two distinct methods, like
int x = obj.getX();
int y = obj.getY();