Java - Czy możliwe jest zwracanie kilku obiektów przez metodę?

Cześć!
Dzisiaj przychodzę z pytaniem jak w temacie, czy możliwe jest w Javie zwrócenie przez metodę kilku obiektów jednocześnie? Załóżmy, że chcę stworzyć taką metodę (nie dałem pętli, żeby było łatwiej zrozumieć, by to co chcę zrobić było lepiej widoczne):


Jak ma wyglądać w tym przypadku return?

Możesz je zwrócić przez referencję, przy pomocy tablicy bądź jakiejś listy, albo zrobić jakąś własną klasę bundlera który to opakuje i jego będziesz zwracał.

Jak wyżej + nieco upraszczając zamiast zwracać “Location” zwracaj “Location[]”.
W C# mogą do tego również służyć “Tuple”, na zasadzie
return ( name="Ala", text="Ma Kota", age=123 )

i wywołanie

(string name, string text, int age) = MojaFunkcja();

Ale Java chyba czegoś takiego nie ma.

@kowgli takie coś nawet jest w tak “złym”, “znienawidzonym” i “zacofanym” C++ :rofl:.

OK. W C# generyczny typ Tuple<T1, T2, …> był od zawsze. W Javie na pewno podobnie. Jeśli mamy do zwrócenia konkretną ilość nazwanych obiektów to jest to dobre rozwiązanie. Zamiast tworzyć na potrzeby jednej metody osobną klasę kontener.

Od jakiegoś czasu możliwy jest również przytoczony wyżej zapis, czego chyba w Javie nie ma. Nie kojarzę też w C++, ale moja znajomość obu języków jest jedynie na poziomie studenckim.

Jest coś takiego w Javie?

(string, string, int) GetValues()
{
	return ("Ala", "ma", 123);
}

// ...

(string x, string y, int z) = GetValues();

// Każde z powyższych jest pełnoprawną "osobną" zmienną
Console.WriteLine(x);
Console.WriteLine(y);
Console.WriteLine(z);

// Można też tak
(string, string, int) result = GetValues();

Console.WriteLine(result.x);
Console.WriteLine(result.y);
Console.WriteLine(result.z);

// Albo
(string, string, int) result = GetValues();
(string x, string y, int z) = result;

Console.WriteLine(x);
Console.WriteLine(y);
Console.WriteLine(z);

Jest, przykład z cppreference:

std::tuple<double, char, std::string> get_student(int id)
{
    if (id == 0) return std::make_tuple(3.8, 'A', "Lisa Simpson");
    if (id == 1) return std::make_tuple(2.9, 'C', "Milhouse Van Houten");
    if (id == 2) return std::make_tuple(1.7, 'D', "Ralph Wiggum");
    throw std::invalid_argument("id");
}
 
int main()
{
    auto student0 = get_student(0);
    std::cout << "ID: 0, "
              << "GPA: " << std::get<0>(student0) << ", "
              << "grade: " << std::get<1>(student0) << ", "
              << "name: " << std::get<2>(student0) << '\n';
 
    double gpa1;
    char grade1;
    std::string name1;
    std::tie(gpa1, grade1, name1) = get_student(1);
    std::cout << "ID: 1, "
              << "GPA: " << gpa1 << ", "
              << "grade: " << grade1 << ", "
              << "name: " << name1 << '\n';
 
    // C++17 structured binding:
    auto [ gpa2, grade2, name2 ] = get_student(2);
    std::cout << "ID: 2, "
              << "GPA: " << gpa2 << ", "
              << "grade: " << grade2 << ", "
              << "name: " << name2 << '\n';
}

W przypadku C++17 wygląda to prawie tak samo jak w C#, nawet i lepiej bo nie trzeba nawet podawać typów zmiennych :slight_smile:.

PS. Nie chcę tutaj zaczynać wojny który język jest najlepszy bo żaden nie jest. Po prostu piszę to w formie edukacyjnej i informacyjnej, a samego C# (wraz z .net’em) uważam, za świetny, przemyślany i ładny pod kątem składni język. Jedyną dla mnie wadą jest to, że jest on praktycznie uwiązany do Windowsa. Owszem można pisać w nim pod linuxa, ale to już nie jest to samo :cry:.

Okej, spróbuję niedługo, tylko dokończę aktualny kod, bo przepisuje nazwy pól, a jest ich całkiem sporo :stuck_out_tongue: W końcu cala tablica monopoly musi zostać przeniesiona

No to fajnie. C++ ma generalnie wszystko. W C# też nie trzeba podawać typów. Ja jednak wolę, bo od razu widać z czym ma się do czynienia. Nie trzeba nigdzie grzebać, aby się dowiedzieć.

1 polubienie